Merge branch 'for-2.6.22' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus...
Linus Torvalds [Mon, 30 Apr 2007 15:10:12 +0000 (08:10 -0700)]
* 'for-2.6.22' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (255 commits)
  [POWERPC] Remove dev_dbg redefinition in drivers/ps3/vuart.c
  [POWERPC] remove kernel module option for booke wdt
  [POWERPC] Avoid putting cpu node twice
  [POWERPC] Spinlock initializer cleanup
  [POWERPC] ppc4xx_sgdma needs dma-mapping.h
  [POWERPC] arch/powerpc/sysdev/timer.c build fix
  [POWERPC] get_property cleanups
  [POWERPC] Remove the unused HTDMSOUND driver
  [POWERPC] cell: cbe_cpufreq cleanup and crash fix
  [POWERPC] Declare enable_kernel_spe in a header
  [POWERPC] Add dt_xlate_addr() to bootwrapper
  [POWERPC] bootwrapper: CONFIG_ -> CONFIG_DEVICE_TREE
  [POWERPC] Don't define a custom bd_t for Xilixn Virtex based boards.
  [POWERPC] Add sane defaults for Xilinx EDK generated xparameters files
  [POWERPC] Add uartlite boot console driver for the zImage wrapper
  [POWERPC] Stop using ppc_sys for Xilinx Virtex boards
  [POWERPC] New registration for common Xilinx Virtex ppc405 platform devices
  [POWERPC] Merge common virtex header files
  [POWERPC] Rework Kconfig dependancies for Xilinx Virtex ppc405 platform
  [POWERPC] Clean up cpufreq Kconfig dependencies
  ...

284 files changed:
Documentation/DocBook/kernel-api.tmpl
Documentation/kernel-parameters.txt
Documentation/networking/bcm43xx.txt
Documentation/sony-laptop.txt
Documentation/thinkpad-acpi.txt [moved from Documentation/ibm-acpi.txt with 60% similarity]
Documentation/video4linux/meye.txt
MAINTAINERS
arch/i386/defconfig
arch/i386/kernel/acpi/earlyquirk.c
arch/mips/mips-boards/sim/Makefile
arch/mips/mips-boards/sim/sim_platform.c [new file with mode: 0644]
arch/parisc/configs/c3000_defconfig
arch/powerpc/sysdev/qe_lib/ucc_fast.c
arch/x86_64/defconfig
crypto/michael_mic.c
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/acpi_memhotplug.c
drivers/acpi/bus.c
drivers/acpi/container.c
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/i2c_ec.c [deleted file]
drivers/acpi/i2c_ec.h [deleted file]
drivers/acpi/ibm_acpi.c [deleted file]
drivers/acpi/processor_core.c
drivers/acpi/processor_idle.c
drivers/acpi/sbs.c
drivers/acpi/scan.c
drivers/acpi/sleep/proc.c
drivers/acpi/tables/tbfadt.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/ahci.c
drivers/ata/ata_generic.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/libata.h
drivers/ata/pata_ali.c
drivers/ata/pata_amd.c
drivers/ata/pata_artop.c
drivers/ata/pata_atiixp.c
drivers/ata/pata_cmd640.c [new file with mode: 0644]
drivers/ata/pata_cmd64x.c
drivers/ata/pata_cs5520.c
drivers/ata/pata_cs5530.c
drivers/ata/pata_cs5535.c
drivers/ata/pata_cypress.c
drivers/ata/pata_efar.c
drivers/ata/pata_hpt366.c
drivers/ata/pata_hpt37x.c
drivers/ata/pata_hpt3x2n.c
drivers/ata/pata_hpt3x3.c
drivers/ata/pata_isapnp.c
drivers/ata/pata_it8213.c
drivers/ata/pata_it821x.c
drivers/ata/pata_ixp4xx_cf.c
drivers/ata/pata_legacy.c
drivers/ata/pata_marvell.c
drivers/ata/pata_mpc52xx.c
drivers/ata/pata_mpiix.c
drivers/ata/pata_netcell.c
drivers/ata/pata_ns87410.c
drivers/ata/pata_oldpiix.c
drivers/ata/pata_opti.c
drivers/ata/pata_optidma.c
drivers/ata/pata_pcmcia.c
drivers/ata/pata_pdc2027x.c
drivers/ata/pata_pdc202xx_old.c
drivers/ata/pata_platform.c
drivers/ata/pata_qdi.c
drivers/ata/pata_radisys.c
drivers/ata/pata_rz1000.c
drivers/ata/pata_sc1200.c
drivers/ata/pata_scc.c
drivers/ata/pata_serverworks.c
drivers/ata/pata_sil680.c
drivers/ata/pata_sis.c
drivers/ata/pata_sl82c105.c
drivers/ata/pata_triflex.c
drivers/ata/pata_via.c
drivers/ata/pata_winbond.c
drivers/ata/pdc_adma.c
drivers/ata/sata_inic162x.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/ata/sata_promise.c
drivers/ata/sata_qstor.c
drivers/ata/sata_sil.c
drivers/ata/sata_sil24.c
drivers/ata/sata_sis.c
drivers/ata/sata_svw.c
drivers/ata/sata_sx4.c
drivers/ata/sata_uli.c
drivers/ata/sata_via.c
drivers/ata/sata_vsc.c
drivers/char/sonypi.c
drivers/clocksource/acpi_pm.c
drivers/media/video/Kconfig
drivers/media/video/meye.c
drivers/media/video/meye.h
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/asus-laptop.c
drivers/misc/sony-laptop.c
drivers/misc/thinkpad_acpi.c [new file with mode: 0644]
drivers/misc/thinkpad_acpi.h [new file with mode: 0644]
drivers/net/3c509.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/chelsio/Makefile
drivers/net/chelsio/common.h
drivers/net/chelsio/cphy.h
drivers/net/chelsio/gmac.h
drivers/net/chelsio/ixf1010.c [deleted file]
drivers/net/chelsio/mac.c
drivers/net/chelsio/mv88e1xxx.c
drivers/net/chelsio/mv88x201x.c
drivers/net/chelsio/my3126.c
drivers/net/chelsio/pm3393.c
drivers/net/chelsio/subr.c
drivers/net/chelsio/vsc7326.c
drivers/net/chelsio/vsc8244.c [deleted file]
drivers/net/chelsio/vsc8244_reg.h [deleted file]
drivers/net/e100.c
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_main.c
drivers/net/e1000/e1000_param.c
drivers/net/eexpress.c
drivers/net/ehea/ehea.h
drivers/net/ehea/ehea_ethtool.c
drivers/net/ehea/ehea_main.c
drivers/net/ehea/ehea_phyp.c
drivers/net/ehea/ehea_phyp.h
drivers/net/ehea/ehea_qmr.c
drivers/net/ehea/ehea_qmr.h
drivers/net/hamradio/baycom_ser_fdx.c
drivers/net/ibmveth.c
drivers/net/ixgb/ixgb.h
drivers/net/ixgb/ixgb_ethtool.c
drivers/net/ixgb/ixgb_main.c
drivers/net/ixgb/ixgb_param.c
drivers/net/mii.c
drivers/net/mipsnet.c
drivers/net/mv643xx_eth.c
drivers/net/mv643xx_eth.h
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_ethtool.c
drivers/net/netxen/netxen_nic_hdr.h
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_hw.h
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_isr.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/netxen/netxen_nic_niu.c
drivers/net/netxen/netxen_nic_phan_reg.h
drivers/net/pcnet32.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/qla3xxx.c
drivers/net/qla3xxx.h
drivers/net/s2io-regs.h
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/sb1250-mac.c
drivers/net/sgiseeq.c
drivers/net/sk98lin/skge.c
drivers/net/skfp/h/lnkstat.h [deleted file]
drivers/net/skge.c
drivers/net/skge.h
drivers/net/smc911x.c
drivers/net/tc35815.c
drivers/net/tulip/dmfe.c
drivers/net/tulip/interrupt.c
drivers/net/tulip/media.c
drivers/net/tulip/tulip.h
drivers/net/tulip/tulip_core.c
drivers/net/tulip/winbond-840.c
drivers/net/ucc_geth.c
drivers/net/ucc_geth.h
drivers/net/ucc_geth_mii.c [new file with mode: 0644]
drivers/net/ucc_geth_mii.h [new file with mode: 0644]
drivers/net/ucc_geth_phy.c [deleted file]
drivers/net/ucc_geth_phy.h [deleted file]
drivers/net/wan/hdlc_cisco.c
drivers/net/wan/hdlc_fr.c
drivers/net/wireless/Kconfig
drivers/net/wireless/Makefile
drivers/net/wireless/README [deleted file]
drivers/net/wireless/airo.c
drivers/net/wireless/bcm43xx/bcm43xx.h
drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/bcm43xx/bcm43xx_phy.c
drivers/net/wireless/bcm43xx/bcm43xx_phy.h
drivers/net/wireless/bcm43xx/bcm43xx_radio.c
drivers/net/wireless/hostap/hostap_ap.c
drivers/net/wireless/hostap/hostap_common.h
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/hostap/hostap_hw.c
drivers/net/wireless/hostap/hostap_main.c
drivers/net/wireless/hostap/hostap_pci.c
drivers/net/wireless/hostap/hostap_plx.c
drivers/net/wireless/ipw2100.c
drivers/net/wireless/ipw2200.c
drivers/net/wireless/libertas/11d.c [new file with mode: 0644]
drivers/net/wireless/libertas/11d.h [new file with mode: 0644]
drivers/net/wireless/libertas/LICENSE [new file with mode: 0644]
drivers/net/wireless/libertas/Makefile [new file with mode: 0644]
drivers/net/wireless/libertas/README [new file with mode: 0644]
drivers/net/wireless/libertas/assoc.c [new file with mode: 0644]
drivers/net/wireless/libertas/assoc.h [new file with mode: 0644]
drivers/net/wireless/libertas/cmd.c [new file with mode: 0644]
drivers/net/wireless/libertas/cmdresp.c [new file with mode: 0644]
drivers/net/wireless/libertas/debugfs.c [new file with mode: 0644]
drivers/net/wireless/libertas/debugfs.h [new file with mode: 0644]
drivers/net/wireless/libertas/decl.h [new file with mode: 0644]
drivers/net/wireless/libertas/defs.h [new file with mode: 0644]
drivers/net/wireless/libertas/dev.h [new file with mode: 0644]
drivers/net/wireless/libertas/ethtool.c [new file with mode: 0644]
drivers/net/wireless/libertas/fw.c [new file with mode: 0644]
drivers/net/wireless/libertas/fw.h [new file with mode: 0644]
drivers/net/wireless/libertas/host.h [new file with mode: 0644]
drivers/net/wireless/libertas/hostcmd.h [new file with mode: 0644]
drivers/net/wireless/libertas/if_bootcmd.c [new file with mode: 0644]
drivers/net/wireless/libertas/if_usb.c [new file with mode: 0644]
drivers/net/wireless/libertas/if_usb.h [new file with mode: 0644]
drivers/net/wireless/libertas/ioctl.c [new file with mode: 0644]
drivers/net/wireless/libertas/join.c [new file with mode: 0644]
drivers/net/wireless/libertas/join.h [new file with mode: 0644]
drivers/net/wireless/libertas/main.c [new file with mode: 0644]
drivers/net/wireless/libertas/radiotap.h [new file with mode: 0644]
drivers/net/wireless/libertas/rx.c [new file with mode: 0644]
drivers/net/wireless/libertas/sbi.h [new file with mode: 0644]
drivers/net/wireless/libertas/scan.c [new file with mode: 0644]
drivers/net/wireless/libertas/scan.h [new file with mode: 0644]
drivers/net/wireless/libertas/thread.h [new file with mode: 0644]
drivers/net/wireless/libertas/tx.c [new file with mode: 0644]
drivers/net/wireless/libertas/types.h [new file with mode: 0644]
drivers/net/wireless/libertas/version.h [new file with mode: 0644]
drivers/net/wireless/libertas/wext.c [new file with mode: 0644]
drivers/net/wireless/libertas/wext.h [new file with mode: 0644]
drivers/net/wireless/todo.txt [deleted file]
drivers/net/wireless/zd1211rw/zd_chip.c
drivers/net/wireless/zd1211rw/zd_chip.h
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/net/wireless/zd1211rw/zd_rf.c
drivers/net/wireless/zd1211rw/zd_rf.h
drivers/net/wireless/zd1211rw/zd_rf_al2230.c
drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/pci/pci-acpi.c
drivers/pci/quirks.c
drivers/scsi/ipr.c
include/acpi/actbl.h
include/asm-powerpc/ucc_fast.h
include/linux/ata.h
include/linux/fsl_devices.h
include/linux/hdlc.h
include/linux/ioport.h
include/linux/libata.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/phy.h
include/linux/sony-laptop.h [new file with mode: 0644]
include/linux/wireless.h
include/net/ieee80211.h
include/net/ieee80211_crypt.h
include/net/ieee80211_radiotap.h
kernel/resource.c
lib/devres.c
net/ieee80211/ieee80211_crypt.c
net/ieee80211/ieee80211_crypt_ccmp.c
net/ieee80211/ieee80211_crypt_tkip.c
net/ieee80211/ieee80211_crypt_wep.c
net/ieee80211/ieee80211_module.c
net/ieee80211/ieee80211_rx.c
net/ieee80211/ieee80211_wx.c

index 0bb9023..b61dfc7 100644 (file)
@@ -236,6 +236,12 @@ X!Ilib/string.c
 !Enet/core/dev.c
 !Enet/ethernet/eth.c
 !Iinclude/linux/etherdevice.h
+!Edrivers/net/phy/phy.c
+!Idrivers/net/phy/phy.c
+!Edrivers/net/phy/phy_device.c
+!Idrivers/net/phy/phy_device.c
+!Edrivers/net/phy/mdio_bus.c
+!Idrivers/net/phy/mdio_bus.c
 <!-- FIXME: Removed for now since no structured comments in source
 X!Enet/core/wireless.c
 -->
index 2017942..84c3bd0 100644 (file)
@@ -181,19 +181,41 @@ and is between 256 and 4096 characters. It is defined in the file
                        that require a timer override, but don't have
                        HPET
 
-       acpi_dbg_layer= [HW,ACPI]
+       acpi.debug_layer=       [HW,ACPI]
                        Format: <int>
                        Each bit of the <int> indicates an ACPI debug layer,
                        1: enable, 0: disable. It is useful for boot time
                        debugging. After system has booted up, it can be set
-                       via /proc/acpi/debug_layer.
-
-       acpi_dbg_level= [HW,ACPI]
+                       via /sys/module/acpi/parameters/debug_layer.
+                       CONFIG_ACPI_DEBUG must be enabled for this to produce any output.
+                       Available bits (add the numbers together) to enable debug output
+                       for specific parts of the ACPI subsystem:
+                       0x01 utilities 0x02 hardware 0x04 events 0x08 tables
+                       0x10 namespace 0x20 parser 0x40 dispatcher
+                       0x80 executer 0x100 resources 0x200 acpica debugger
+                       0x400 os services 0x800 acpica disassembler.
+                       The number can be in decimal or prefixed with 0x in hex.
+                       Warning: Many of these options can produce a lot of
+                       output and make your system unusable. Be very careful.
+
+       acpi.debug_level=       [HW,ACPI]
                        Format: <int>
                        Each bit of the <int> indicates an ACPI debug level,
                        1: enable, 0: disable. It is useful for boot time
                        debugging. After system has booted up, it can be set
-                       via /proc/acpi/debug_level.
+                       via /sys/module/acpi/parameters/debug_level.
+                       CONFIG_ACPI_DEBUG must be enabled for this to produce any output.
+                       Available bits (add the numbers together) to enable different
+                       debug output levels of the ACPI subsystem:
+                       0x01 error 0x02 warn 0x04 init 0x08 debug object
+                       0x10 info 0x20 init names 0x40 parse 0x80 load
+                       0x100 dispatch 0x200 execute 0x400 names 0x800 operation region
+                       0x1000 bfield 0x2000 tables 0x4000 values 0x8000 objects
+                       0x10000 resources 0x20000 user requests 0x40000 package.
+                       The number can be in decimal or prefixed with 0x in hex.
+                       Warning: Many of these options can produce a lot of
+                       output and make your system unusable. Be very careful.
+
 
        acpi_fake_ecdt  [HW,ACPI] Workaround failure due to BIOS lacking ECDT
 
index 28541d2..a136721 100644 (file)
@@ -2,35 +2,88 @@
                        BCM43xx Linux Driver Project
                        ============================
 
-About this software
--------------------
+Introduction
+------------
 
-The goal of this project is to develop a linux driver for Broadcom
-BCM43xx chips, based on the specification at 
-http://bcm-specs.sipsolutions.net/
+Many of the wireless devices found in modern notebook computers are
+based on the wireless chips produced by Broadcom. These devices have
+been a problem for Linux users as there is no open-source driver
+available. In addition, Broadcom has not released specifications
+for the device, and driver availability has been limited to the
+binary-only form used in the GPL versions of AP hardware such as the
+Linksys WRT54G, and the Windows and OS X drivers.  Before this project
+began, the only way to use these devices were to use the Windows or
+OS X drivers with either the Linuxant or ndiswrapper modules. There
+is a strong penalty if this method is used as loading the binary-only
+module "taints" the kernel, and no kernel developer will help diagnose
+any kernel problems.
 
-The project page is http://bcm43xx.berlios.de/
+Development
+-----------
 
+This driver has been developed using
+a clean-room technique that is described at
+http://bcm-specs.sipsolutions.net/ReverseEngineeringProcess. For legal
+reasons, none of the clean-room crew works on the on the Linux driver,
+and none of the Linux developers sees anything but the specifications,
+which are the ultimate product of the reverse-engineering group.
 
-Requirements
-------------
+Software
+--------
+
+Since the release of the 2.6.17 kernel, the bcm43xx driver has been
+distributed with the kernel source, and is prebuilt in most, if not
+all, distributions.  There is, however, additional software that is
+required. The firmware used by the chip is the intellectual property
+of Broadcom and they have not given the bcm43xx team redistribution
+rights to this firmware.  Since we cannot legally redistribute
+the firwmare we cannot include it with the driver. Furthermore, it
+cannot be placed in the downloadable archives of any distributing
+organization; therefore, the user is responsible for obtaining the
+firmware and placing it in the appropriate location so that the driver
+can find it when initializing.
+
+To help with this process, the bcm43xx developers provide a separate
+program named bcm43xx-fwcutter to "cut" the firmware out of a
+Windows or OS X driver and write the extracted files to the proper
+location. This program is usually provided with the distribution;
+however, it may be downloaded from
+
+http://developer.berlios.de/project/showfiles.php?group_id=4547
 
-1)     Linux Kernel 2.6.16 or later
-       http://www.kernel.org/
+The firmware is available in two versions. V3 firmware is used with
+the in-kernel bcm43xx driver that uses a software MAC layer called
+SoftMAC, and will have a microcode revision of 0x127 or smaller. The
+V4 firmware is used by an out-of-kernel driver employing a variation of
+the Devicescape MAC layer known as d80211. Once bcm43xx-d80211 reaches
+a satisfactory level of development, it will replace bcm43xx-softmac
+in the kernel as it is much more flexible and powerful.
 
-       You may want to configure your kernel with:
+A source for the latest V3 firmware is
 
-       CONFIG_DEBUG_FS (optional):
-               -> Kernel hacking
-                 -> Debug Filesystem
+http://downloads.openwrt.org/sources/wl_apsta-3.130.20.0.o
 
-2)     SoftMAC IEEE 802.11 Networking Stack extension and patched ieee80211
-       modules:
-       http://softmac.sipsolutions.net/
+Once this file is downloaded, the command
+'bcm43xx-fwcutter -w <dir> <filename>'
+will extract the microcode and write it to directory
+<dir>. The correct directory will depend on your distribution;
+however, most use '/lib/firmware'. Once this step is completed,
+the bcm3xx driver should load when the system is booted. To see
+any messages relating to the driver, issue the command 'dmesg |
+grep bcm43xx' from a terminal window. If there are any problems,
+please send that output to Bcm43xx-dev@lists.berlios.de.
 
-3)     Firmware Files
+Although the driver has been in-kernel since 2.6.17, the earliest
+version is quite limited in its capability. Patches that include
+all features of later versions are available for the stable kernel
+versions from 2.6.18. These will be needed if you use a BCM4318,
+or a PCI Express version (BCM4311 and BCM4312). In addition, if you
+have an early BCM4306 and more than 1 GB RAM, your kernel will need
+to be patched. These patches, which are being updated regularly,
+are available at ftp://lwfinger.dynalias.org/patches. Look for
+combined_2.6.YY.patch. Of course you will need kernel source downloaded
+from kernel.org, or the source from your distribution.
 
-       Please try fwcutter. Fwcutter can extract the firmware from various 
-       binary driver files. It supports driver files from Windows, MacOS and 
-       Linux. You can get fwcutter from http://bcm43xx.berlios.de/.
-       Also, fwcutter comes with a README file for further instructions.
+If you build your own kernel, please enable CONFIG_BCM43XX_DEBUG
+and CONFIG_IEEE80211_SOFTMAC_DEBUG. The log information provided is
+essential for solving any problems.
index dfd26df..7a5c1a8 100644 (file)
@@ -3,12 +3,18 @@ Sony Notebook Control Driver (SNC) Readme
        Copyright (C) 2004- 2005 Stelian Pop <stelian@popies.net>
        Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
 
-This mini-driver drives the SNC device present in the ACPI BIOS of
-the Sony Vaio laptops.
+This mini-driver drives the SNC and SPIC device present in the ACPI BIOS of the
+Sony Vaio laptops. This driver mixes both devices functions under the same
+(hopefully consistent) interface. This also means that the sonypi driver is
+obsoleted by sony-laptop now.
 
-It gives access to some extra laptop functionalities. In its current
-form, this driver let the user set or query the screen brightness
-through the backlight subsystem and remove/apply power to some devices.
+Fn keys (hotkeys):
+------------------
+Some models report hotkeys through the SNC or SPIC devices, such events are
+reported both through the ACPI subsystem as acpi events and through the INPUT
+subsystem. See the logs of acpid or /proc/acpi/event and
+/proc/bus/input/devices to find out what those events are and which input
+devices are created by the driver.
 
 Backlight control:
 ------------------
@@ -39,6 +45,8 @@ The files are:
        audiopower              power on/off the internal sound card
        lanpower                power on/off the internal ethernet card
                                (only in debug mode)
+       bluetoothpower          power on/off the internal bluetooth device
+       fanspeed                get/set the fan speed
 
 Note that some files may be missing if they are not supported
 by your particular laptop model.
@@ -76,9 +84,9 @@ The sony-laptop driver creates, for some of those methods (the most
 current ones found on several Vaio models), an entry under
 /sys/devices/platform/sony-laptop, just like the 'cdpower' one.
 You can create other entries corresponding to your own laptop methods by
-further editing the source (see the 'sony_acpi_values' table, and add a new
+further editing the source (see the 'sony_nc_values' table, and add a new
 entry to this table with your get/set method names using the
-HANDLE_NAMES macro).
+SNC_HANDLE_NAMES macro).
 
 Your mission, should you accept it, is to try finding out what
 those entries are for, by reading/writing random values from/to those
@@ -87,6 +95,9 @@ files and find out what is the impact on your laptop.
 Should you find anything interesting, please report it back to me,
 I will not disavow all knowledge of your actions :)
 
+See also http://www.linux.it/~malattia/wiki/index.php/Sony_drivers for other
+useful info.
+
 Bugs/Limitations:
 -----------------
 
similarity index 60%
rename from Documentation/ibm-acpi.txt
rename to Documentation/thinkpad-acpi.txt
index 0132d36..2d48033 100644 (file)
@@ -1,16 +1,22 @@
-                   IBM ThinkPad ACPI Extras Driver
+                    ThinkPad ACPI Extras Driver
 
-                            Version 0.12
-                           17 August 2005
+                            Version 0.14
+                          April 21st, 2007
 
                Borislav Deianov <borislav@users.sf.net>
+            Henrique de Moraes Holschuh <hmh@hmh.eng.br>
                      http://ibm-acpi.sf.net/
 
 
-This is a Linux ACPI driver for the IBM ThinkPad laptops. It supports
-various features of these laptops which are accessible through the
-ACPI framework but not otherwise supported by the generic Linux ACPI
-drivers.
+This is a Linux driver for the IBM and Lenovo ThinkPad laptops. It
+supports various features of these laptops which are accessible
+through the ACPI and ACPI EC framework, but not otherwise fully
+supported by the generic Linux ACPI drivers.
+
+This driver used to be named ibm-acpi until kernel 2.6.21 and release
+0.13-20070314.  It used to be in the drivers/acpi tree, but it was
+moved to the drivers/misc tree and renamed to thinkpad-acpi for kernel
+2.6.22, and release 0.14.
 
 
 Status
@@ -21,7 +27,7 @@ detailed description):
 
        - Fn key combinations
        - Bluetooth enable and disable
-       - video output switching, expansion control     
+       - video output switching, expansion control
        - ThinkLight on and off
        - limited docking and undocking
        - UltraBay eject
@@ -32,7 +38,7 @@ detailed description):
        - Experimental: embedded controller register dump
        - LCD brightness control
        - Volume control
-       - Experimental: fan speed, fan enable/disable
+       - Fan control and monitoring: fan speed, fan enable/disable
        - Experimental: WAN enable and disable
 
 A compatibility table by model and feature is maintained on the web
@@ -42,6 +48,8 @@ Please include the following information in your report:
 
        - ThinkPad model name
        - a copy of your DSDT, from /proc/acpi/dsdt
+       - a copy of the output of dmidecode, with serial numbers
+         and UUIDs masked off
        - which driver features work and which don't
        - the observed behavior of non-working features
 
@@ -52,25 +60,85 @@ Installation
 ------------
 
 If you are compiling this driver as included in the Linux kernel
-sources, simply enable the CONFIG_ACPI_IBM option (Power Management /
-ACPI / IBM ThinkPad Laptop Extras).
+sources, simply enable the CONFIG_THINKPAD_ACPI option, and optionally
+enable the CONFIG_THINKPAD_ACPI_BAY option if you want the
+thinkpad-specific bay functionality.
 
 Features
 --------
 
-The driver creates the /proc/acpi/ibm directory. There is a file under
-that directory for each feature described below. Note that while the
-driver is still in the alpha stage, the exact proc file format and
-commands supported by the various features is guaranteed to change
-frequently.
+The driver exports two different interfaces to userspace, which can be
+used to access the features it provides.  One is a legacy procfs-based
+interface, which will be removed at some time in the distant future.
+The other is a new sysfs-based interface which is not complete yet.
 
-Driver version -- /proc/acpi/ibm/driver
----------------------------------------
+The procfs interface creates the /proc/acpi/ibm directory.  There is a
+file under that directory for each feature it supports.  The procfs
+interface is mostly frozen, and will change very little if at all: it
+will not be extended to add any new functionality in the driver, instead
+all new functionality will be implemented on the sysfs interface.
+
+The sysfs interface tries to blend in the generic Linux sysfs subsystems
+and classes as much as possible.  Since some of these subsystems are not
+yet ready or stabilized, it is expected that this interface will change,
+and any and all userspace programs must deal with it.
+
+
+Notes about the sysfs interface:
+
+Unlike what was done with the procfs interface, correctness when talking
+to the sysfs interfaces will be enforced, as will correctness in the
+thinkpad-acpi's implementation of sysfs interfaces.
+
+Also, any bugs in the thinkpad-acpi sysfs driver code or in the
+thinkpad-acpi's implementation of the sysfs interfaces will be fixed for
+maximum correctness, even if that means changing an interface in
+non-compatible ways.  As these interfaces mature both in the kernel and
+in thinkpad-acpi, such changes should become quite rare.
+
+Applications interfacing to the thinkpad-acpi sysfs interfaces must
+follow all sysfs guidelines and correctly process all errors (the sysfs
+interface makes extensive use of errors).  File descriptors and open /
+close operations to the sysfs inodes must also be properly implemented.
+
+The version of thinkpad-acpi's sysfs interface is exported by the driver
+as a driver attribute (see below).
+
+Sysfs driver attributes are on the driver's sysfs attribute space,
+for 2.6.20 this is /sys/bus/platform/drivers/thinkpad-acpi/.
+
+Sysfs device attributes are on the driver's sysfs attribute space,
+for 2.6.20 this is /sys/devices/platform/thinkpad-acpi/.
+
+Driver version
+--------------
+
+procfs: /proc/acpi/ibm/driver
+sysfs driver attribute: version
 
 The driver name and version. No commands can be written to this file.
 
-Hot keys -- /proc/acpi/ibm/hotkey
----------------------------------
+Sysfs interface version
+-----------------------
+
+sysfs driver attribute: interface_version
+
+Version of the thinkpad-acpi sysfs interface, as an unsigned long
+(output in hex format: 0xAAAABBCC), where:
+       AAAA - major revision
+       BB - minor revision
+       CC - bugfix revision
+
+The sysfs interface version changelog for the driver can be found at the
+end of this document.  Changes to the sysfs interface done by the kernel
+subsystems are not documented here, nor are they tracked by this
+attribute.
+
+Hot keys
+--------
+
+procfs: /proc/acpi/ibm/hotkey
+sysfs device attribute: hotkey/*
 
 Without this driver, only the Fn-F4 key (sleep button) generates an
 ACPI event. With the driver loaded, the hotkey feature enabled and the
@@ -84,15 +152,6 @@ All labeled Fn-Fx key combinations generate distinct events. In
 addition, the lid microswitch and some docking station buttons may
 also generate such events.
 
-The following commands can be written to this file:
-
-       echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature
-       echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature
-       echo 0xffff > /proc/acpi/ibm/hotkey -- enable all possible hot keys
-       echo 0x0000 > /proc/acpi/ibm/hotkey -- disable all possible hot keys
-       ... any other 4-hex-digit mask ...
-       echo reset > /proc/acpi/ibm/hotkey -- restore the original mask
-
 The bit mask allows some control over which hot keys generate ACPI
 events. Not all bits in the mask can be modified. Not all bits that
 can be modified do anything. Not all hot keys can be individually
@@ -124,15 +183,77 @@ buttons do not generate ACPI events even with this driver. They *can*
 be used through the "ThinkPad Buttons" utility, see
 http://www.nongnu.org/tpb/
 
-Bluetooth -- /proc/acpi/ibm/bluetooth
--------------------------------------
+procfs notes:
+
+The following commands can be written to the /proc/acpi/ibm/hotkey file:
+
+       echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature
+       echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature
+       echo 0xffff > /proc/acpi/ibm/hotkey -- enable all possible hot keys
+       echo 0x0000 > /proc/acpi/ibm/hotkey -- disable all possible hot keys
+       ... any other 4-hex-digit mask ...
+       echo reset > /proc/acpi/ibm/hotkey -- restore the original mask
+
+sysfs notes:
+
+       The hot keys attributes are in a hotkey/ subdirectory off the
+       thinkpad device.
+
+       bios_enabled:
+               Returns the status of the hot keys feature when
+               thinkpad-acpi was loaded.  Upon module unload, the hot
+               key feature status will be restored to this value.
+
+               0: hot keys were disabled
+               1: hot keys were enabled
+
+       bios_mask:
+               Returns the hot keys mask when thinkpad-acpi was loaded.
+               Upon module unload, the hot keys mask will be restored
+               to this value.
+
+       enable:
+               Enables/disables the hot keys feature, and reports
+               current status of the hot keys feature.
+
+               0: disables the hot keys feature / feature disabled
+               1: enables the hot keys feature / feature enabled
+
+       mask:
+               bit mask to enable ACPI event generation for each hot
+               key (see above).  Returns the current status of the hot
+               keys mask, and allows one to modify it.
+
 
-This feature shows the presence and current state of a Bluetooth
-device. If Bluetooth is installed, the following commands can be used:
+Bluetooth
+---------
+
+procfs: /proc/acpi/ibm/bluetooth
+sysfs device attribute: bluetooth/enable
+
+This feature shows the presence and current state of a ThinkPad
+Bluetooth device in the internal ThinkPad CDC slot.
+
+Procfs notes:
+
+If Bluetooth is installed, the following commands can be used:
 
        echo enable > /proc/acpi/ibm/bluetooth
        echo disable > /proc/acpi/ibm/bluetooth
 
+Sysfs notes:
+
+       If the Bluetooth CDC card is installed, it can be enabled /
+       disabled through the "bluetooth/enable" thinkpad-acpi device
+       attribute, and its current status can also be queried.
+
+       enable:
+               0: disables Bluetooth / Bluetooth is disabled
+               1: enables Bluetooth / Bluetooth is enabled.
+
+       Note: this interface will be probably be superseeded by the
+       generic rfkill class.
+
 Video output control -- /proc/acpi/ibm/video
 --------------------------------------------
 
@@ -209,7 +330,7 @@ hot plugging of devices in the Linux ACPI framework. If the laptop was
 booted while not in the dock, the following message is shown in the
 logs:
 
-       Mar 17 01:42:34 aero kernel: ibm_acpi: dock device not present
+       Mar 17 01:42:34 aero kernel: thinkpad_acpi: dock device not present
 
 In this case, no dock-related events are generated but the dock and
 undock commands described below still work. They can be executed
@@ -269,7 +390,7 @@ This is due to the current lack of support for hot plugging of devices
 in the Linux ACPI framework. If the laptop was booted without the
 UltraBay, the following message is shown in the logs:
 
-       Mar 17 01:42:34 aero kernel: ibm_acpi: bay device not present
+       Mar 17 01:42:34 aero kernel: thinkpad_acpi: bay device not present
 
 In this case, no bay-related events are generated but the eject
 command described below still works. It can be executed manually or
@@ -313,23 +434,19 @@ supported. Use "eject2" instead of "eject" for the second bay.
 Note: the UltraBay eject support on the 600e/x, A22p and A3x is
 EXPERIMENTAL and may not work as expected. USE WITH CAUTION!
 
-CMOS control -- /proc/acpi/ibm/cmos
------------------------------------
+CMOS control
+------------
+
+procfs: /proc/acpi/ibm/cmos
+sysfs device attribute: cmos_command
 
 This feature is used internally by the ACPI firmware to control the
 ThinkLight on most newer ThinkPad models. It may also control LCD
 brightness, sounds volume and more, but only on some models.
 
-The commands are non-negative integer numbers:
-
-       echo 0 >/proc/acpi/ibm/cmos
-       echo 1 >/proc/acpi/ibm/cmos
-       echo 2 >/proc/acpi/ibm/cmos
-       ...
-
-The range of valid numbers is 0 to 21, but not all have an effect and
-the behavior varies from model to model. Here is the behavior on the
-X40 (tpb is the ThinkPad Buttons utility):
+The range of valid cmos command numbers is 0 to 21, but not all have an
+effect and the behavior varies from model to model.  Here is the behavior
+on the X40 (tpb is the ThinkPad Buttons utility):
 
        0 - no effect but tpb reports "Volume down"
        1 - no effect but tpb reports "Volume up"
@@ -342,6 +459,9 @@ X40 (tpb is the ThinkPad Buttons utility):
        13 - ThinkLight off
        14 - no effect but tpb reports ThinkLight status change
 
+The cmos command interface is prone to firmware split-brain problems, as
+in newer ThinkPads it is just a compatibility layer.
+
 LED control -- /proc/acpi/ibm/led
 ---------------------------------
 
@@ -393,17 +513,17 @@ X40:
        16 - one medium-pitched beep repeating constantly, stop with 17
        17 - stop 16
 
-Temperature sensors -- /proc/acpi/ibm/thermal
----------------------------------------------
+Temperature sensors
+-------------------
+
+procfs: /proc/acpi/ibm/thermal
+sysfs device attributes: (hwmon) temp*_input
 
 Most ThinkPads include six or more separate temperature sensors but
 only expose the CPU temperature through the standard ACPI methods.
 This feature shows readings from up to eight different sensors on older
 ThinkPads, and it has experimental support for up to sixteen different
-sensors on newer ThinkPads.  Readings from sensors that are not available
-return -128.
-
-No commands can be written to this file.
+sensors on newer ThinkPads.
 
 EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the
 implementation directly accesses hardware registers and may not work as
@@ -460,6 +580,20 @@ The A31 has a very atypical layout for the thermal sensors
 8:  Bay Battery: secondary sensor
 
 
+Procfs notes:
+       Readings from sensors that are not available return -128.
+       No commands can be written to this file.
+
+Sysfs notes:
+       Sensors that are not available return the ENXIO error.  This
+       status may change at runtime, as there are hotplug thermal
+       sensors, like those inside the batteries and docks.
+
+       thinkpad-acpi thermal sensors are reported through the hwmon
+       subsystem, and follow all of the hwmon guidelines at
+       Documentation/hwmon.
+
+
 EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump
 ------------------------------------------------------------------------
 
@@ -472,7 +606,7 @@ This feature dumps the values of 256 embedded controller
 registers. Values which have changed since the last time the registers
 were dumped are marked with a star:
 
-[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump 
+[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump
 EC       +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f
 EC 0x00:  a7  47  87  01  fe  96  00  08  01  00  cb  00  00  00  40  00
 EC 0x10:  00  00  ff  ff  f4  3c  87  09  01  ff  42  01  ff  ff  0d  00
@@ -503,7 +637,7 @@ vary. The second ensures that the fan-related values do vary, since
 the fan speed fluctuates a bit. The third will (hopefully) mark the
 fan register with a star:
 
-[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump 
+[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump
 EC       +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f
 EC 0x00:  a7  47  87  01  fe  96  00  08  01  00  cb  00  00  00  40  00
 EC 0x10:  00  00  ff  ff  f4  3c  87  09  01  ff  42  01  ff  ff  0d  00
@@ -533,19 +667,59 @@ registers contain the current battery capacity, etc. If you experiment
 with this, do send me your results (including some complete dumps with
 a description of the conditions when they were taken.)
 
-LCD brightness control -- /proc/acpi/ibm/brightness
----------------------------------------------------
+LCD brightness control
+----------------------
+
+procfs: /proc/acpi/ibm/brightness
+sysfs backlight device "thinkpad_screen"
 
 This feature allows software control of the LCD brightness on ThinkPad
-models which don't have a hardware brightness slider. The available
-commands are:
+models which don't have a hardware brightness slider.
+
+It has some limitations: the LCD backlight cannot be actually turned on or off
+by this interface, and in many ThinkPad models, the "dim while on battery"
+functionality will be enabled by the BIOS when this interface is used, and
+cannot be controlled.
+
+The backlight control has eight levels, ranging from 0 to 7.  Some of the
+levels may not be distinct.
+
+Procfs notes:
+
+       The available commands are:
 
        echo up   >/proc/acpi/ibm/brightness
        echo down >/proc/acpi/ibm/brightness
        echo 'level <level>' >/proc/acpi/ibm/brightness
 
-The <level> number range is 0 to 7, although not all of them may be
-distinct. The current brightness level is shown in the file.
+Sysfs notes:
+
+The interface is implemented through the backlight sysfs class, which is poorly
+documented at this time.
+
+Locate the thinkpad_screen device under /sys/class/backlight, and inside it
+there will be the following attributes:
+
+       max_brightness:
+               Reads the maximum brightness the hardware can be set to.
+               The minimum is always zero.
+
+       actual_brightness:
+               Reads what brightness the screen is set to at this instant.
+
+       brightness:
+               Writes request the driver to change brightness to the given
+               value.  Reads will tell you what brightness the driver is trying
+               to set the display to when "power" is set to zero and the display
+               has not been dimmed by a kernel power management event.
+
+       power:
+               power management mode, where 0 is "display on", and 1 to 3 will
+               dim the display backlight to brightness level 0 because
+               thinkpad-acpi cannot really turn the backlight off.  Kernel
+               power management events can temporarily increase the current
+               power management level, i.e. they can dim the display.
+
 
 Volume control -- /proc/acpi/ibm/volume
 ---------------------------------------
@@ -563,41 +737,42 @@ distinct. The unmute the volume after the mute command, use either the
 up or down command (the level command will not unmute the volume).
 The current volume level and mute state is shown in the file.
 
-EXPERIMENTAL: fan speed, fan enable/disable -- /proc/acpi/ibm/fan
------------------------------------------------------------------
+Fan control and monitoring: fan speed, fan enable/disable
+---------------------------------------------------------
 
-This feature is marked EXPERIMENTAL because the implementation
-directly accesses hardware registers and may not work as expected. USE
-WITH CAUTION! To use this feature, you need to supply the
-experimental=1 parameter when loading the module.
+procfs: /proc/acpi/ibm/fan
+sysfs device attributes: (hwmon) fan_input, pwm1, pwm1_enable
+
+NOTE NOTE NOTE: fan control operations are disabled by default for
+safety reasons.  To enable them, the module parameter "fan_control=1"
+must be given to thinkpad-acpi.
 
 This feature attempts to show the current fan speed, control mode and
 other fan data that might be available.  The speed is read directly
 from the hardware registers of the embedded controller.  This is known
-to work on later R, T and X series ThinkPads but may show a bogus
+to work on later R, T, X and Z series ThinkPads but may show a bogus
 value on other models.
 
-Most ThinkPad fans work in "levels".  Level 0 stops the fan.  The higher
-the level, the higher the fan speed, although adjacent levels often map
-to the same fan speed.  7 is the highest level, where the fan reaches
-the maximum recommended speed.  Level "auto" means the EC changes the
-fan level according to some internal algorithm, usually based on
-readings from the thermal sensors.  Level "disengaged" means the EC
-disables the speed-locked closed-loop fan control, and drives the fan as
-fast as it can go, which might exceed hardware limits, so use this level
-with caution.
+Fan levels:
 
-The fan usually ramps up or down slowly from one speed to another,
-and it is normal for the EC to take several seconds to react to fan
-commands.
+Most ThinkPad fans work in "levels" at the firmware interface.  Level 0
+stops the fan.  The higher the level, the higher the fan speed, although
+adjacent levels often map to the same fan speed.  7 is the highest
+level, where the fan reaches the maximum recommended speed.
 
-The fan may be enabled or disabled with the following commands:
+Level "auto" means the EC changes the fan level according to some
+internal algorithm, usually based on readings from the thermal sensors.
 
-       echo enable  >/proc/acpi/ibm/fan
-       echo disable >/proc/acpi/ibm/fan
+There is also a "full-speed" level, also known as "disengaged" level.
+In this level, the EC disables the speed-locked closed-loop fan control,
+and drives the fan as fast as it can go, which might exceed hardware
+limits, so use this level with caution.
 
-Placing a fan on level 0 is the same as disabling it.  Enabling a fan
-will try to place it in a safe level if it is too slow or disabled.
+The fan usually ramps up or down slowly from one speed to another, and
+it is normal for the EC to take several seconds to react to fan
+commands.  The full-speed level may take up to two minutes to ramp up to
+maximum speed, and in some ThinkPads, the tachometer readings go stale
+while the EC is transitioning to the full-speed level.
 
 WARNING WARNING WARNING: do not leave the fan disabled unless you are
 monitoring all of the temperature sensor readings and you are ready to
@@ -615,46 +790,146 @@ fan is turned off when the CPU temperature drops to 49 degrees and the
 HDD temperature drops to 41 degrees.  These thresholds cannot
 currently be controlled.
 
+The ThinkPad's ACPI DSDT code will reprogram the fan on its own when
+certain conditions are met.  It will override any fan programming done
+through thinkpad-acpi.
+
+The thinkpad-acpi kernel driver can be programmed to revert the fan
+level to a safe setting if userspace does not issue one of the procfs
+fan commands: "enable", "disable", "level" or "watchdog", or if there
+are no writes to pwm1_enable (or to pwm1 *if and only if* pwm1_enable is
+set to 1, manual mode) within a configurable amount of time of up to
+120 seconds.  This functionality is called fan safety watchdog.
+
+Note that the watchdog timer stops after it enables the fan.  It will be
+rearmed again automatically (using the same interval) when one of the
+above mentioned fan commands is received.  The fan watchdog is,
+therefore, not suitable to protect against fan mode changes made through
+means other than the "enable", "disable", and "level" procfs fan
+commands, or the hwmon fan control sysfs interface.
+
+Procfs notes:
+
+The fan may be enabled or disabled with the following commands:
+
+       echo enable  >/proc/acpi/ibm/fan
+       echo disable >/proc/acpi/ibm/fan
+
+Placing a fan on level 0 is the same as disabling it.  Enabling a fan
+will try to place it in a safe level if it is too slow or disabled.
+
 The fan level can be controlled with the command:
 
-       echo 'level <level>' > /proc/acpi/ibm/thermal
+       echo 'level <level>' > /proc/acpi/ibm/fan
 
-Where <level> is an integer from 0 to 7, or one of the words "auto"
-or "disengaged" (without the quotes).  Not all ThinkPads support the
-"auto" and "disengaged" levels.
+Where <level> is an integer from 0 to 7, or one of the words "auto" or
+"full-speed" (without the quotes).  Not all ThinkPads support the "auto"
+and "full-speed" levels.  The driver accepts "disengaged" as an alias for
+"full-speed", and reports it as "disengaged" for backwards
+compatibility.
 
 On the X31 and X40 (and ONLY on those models), the fan speed can be
-controlled to a certain degree. Once the fan is running, it can be
+controlled to a certain degree.  Once the fan is running, it can be
 forced to run faster or slower with the following command:
 
-       echo 'speed <speed>' > /proc/acpi/ibm/thermal
+       echo 'speed <speed>' > /proc/acpi/ibm/fan
 
-The sustainable range of fan speeds on the X40 appears to be from
-about 3700 to about 7350. Values outside this range either do not have
-any effect or the fan speed eventually settles somewhere in that
-range. The fan cannot be stopped or started with this command.
+The sustainable range of fan speeds on the X40 appears to be from about
+3700 to about 7350. Values outside this range either do not have any
+effect or the fan speed eventually settles somewhere in that range.  The
+fan cannot be stopped or started with this command.  This functionality
+is incomplete, and not available through the sysfs interface.
 
-The ThinkPad's ACPI DSDT code will reprogram the fan on its own when
-certain conditions are met.  It will override any fan programming done
-through ibm-acpi.
+To program the safety watchdog, use the "watchdog" command.
 
-EXPERIMENTAL: WAN -- /proc/acpi/ibm/wan
----------------------------------------
+       echo 'watchdog <interval in seconds>' > /proc/acpi/ibm/fan
+
+If you want to disable the watchdog, use 0 as the interval.
+
+Sysfs notes:
+
+The sysfs interface follows the hwmon subsystem guidelines for the most
+part, and the exception is the fan safety watchdog.
+
+Writes to any of the sysfs attributes may return the EINVAL error if
+that operation is not supported in a given ThinkPad or if the parameter
+is out-of-bounds, and EPERM if it is forbidden.  They may also return
+EINTR (interrupted system call), and EIO (I/O error while trying to talk
+to the firmware).
+
+Features not yet implemented by the driver return ENOSYS.
+
+hwmon device attribute pwm1_enable:
+       0: PWM offline (fan is set to full-speed mode)
+       1: Manual PWM control (use pwm1 to set fan level)
+       2: Hardware PWM control (EC "auto" mode)
+       3: reserved (Software PWM control, not implemented yet)
+
+       Modes 0 and 2 are not supported by all ThinkPads, and the
+       driver is not always able to detect this.  If it does know a
+       mode is unsupported, it will return -EINVAL.
+
+hwmon device attribute pwm1:
+       Fan level, scaled from the firmware values of 0-7 to the hwmon
+       scale of 0-255.  0 means fan stopped, 255 means highest normal
+       speed (level 7).
+
+       This attribute only commands the fan if pmw1_enable is set to 1
+       (manual PWM control).
+
+hwmon device attribute fan1_input:
+       Fan tachometer reading, in RPM.  May go stale on certain
+       ThinkPads while the EC transitions the PWM to offline mode,
+       which can take up to two minutes.  May return rubbish on older
+       ThinkPads.
+
+driver attribute fan_watchdog:
+       Fan safety watchdog timer interval, in seconds.  Minimum is
+       1 second, maximum is 120 seconds.  0 disables the watchdog.
+
+To stop the fan: set pwm1 to zero, and pwm1_enable to 1.
+
+To start the fan in a safe mode: set pwm1_enable to 2.  If that fails
+with EINVAL, try to set pwm1_enable to 1 and pwm1 to at least 128 (255
+would be the safest choice, though).
+
+
+EXPERIMENTAL: WAN
+-----------------
+
+procfs: /proc/acpi/ibm/wan
+sysfs device attribute: wwan/enable
 
 This feature is marked EXPERIMENTAL because the implementation
 directly accesses hardware registers and may not work as expected. USE
 WITH CAUTION! To use this feature, you need to supply the
 experimental=1 parameter when loading the module.
 
-This feature shows the presence and current state of a WAN (Sierra
-Wireless EV-DO) device. If WAN is installed, the following commands can
-be used:
+This feature shows the presence and current state of a W-WAN (Sierra
+Wireless EV-DO) device.
+
+It was tested on a Lenovo Thinkpad X60. It should probably work on other
+Thinkpad models which come with this module installed.
+
+Procfs notes:
+
+If the W-WAN card is installed, the following commands can be used:
 
        echo enable > /proc/acpi/ibm/wan
        echo disable > /proc/acpi/ibm/wan
 
-It was tested on a Lenovo Thinkpad X60. It should probably work on other
-Thinkpad models which come with this module installed.
+Sysfs notes:
+
+       If the W-WAN card is installed, it can be enabled /
+       disabled through the "wwan/enable" thinkpad-acpi device
+       attribute, and its current status can also be queried.
+
+       enable:
+               0: disables WWAN card / WWAN card is disabled
+               1: enables WWAN card / WWAN card is enabled.
+
+       Note: this interface will be probably be superseeded by the
+       generic rfkill class.
 
 Multiple Commands, Module Parameters
 ------------------------------------
@@ -665,64 +940,42 @@ separating them with commas, for example:
        echo enable,0xffff > /proc/acpi/ibm/hotkey
        echo lcd_disable,crt_enable > /proc/acpi/ibm/video
 
-Commands can also be specified when loading the ibm_acpi module, for
-example:
-
-       modprobe ibm_acpi hotkey=enable,0xffff video=auto_disable
-
-The ibm-acpi kernel driver can be programmed to revert the fan level
-to a safe setting if userspace does not issue one of the fan commands:
-"enable", "disable", "level" or "watchdog" within a configurable
-ammount of time.  To do this, use the "watchdog" command.
-
-       echo 'watchdog <interval>' > /proc/acpi/ibm/fan
-
-Interval is the ammount of time in seconds to wait for one of the
-above mentioned fan commands before reseting the fan level to a safe
-one.  If set to zero, the watchdog is disabled (default).  When the
-watchdog timer runs out, it does the exact equivalent of the "enable"
-fan command.
-
-Note that the watchdog timer stops after it enables the fan.  It will
-be rearmed again automatically (using the same interval) when one of
-the above mentioned fan commands is received.  The fan watchdog is,
-therefore, not suitable to protect against fan mode changes made
-through means other than the "enable", "disable", and "level" fan
-commands.
-
-
-Example Configuration
----------------------
-
-The ACPI support in the kernel is intended to be used in conjunction
-with a user-space daemon, acpid. The configuration files for this
-daemon control what actions are taken in response to various ACPI
-events. An example set of configuration files are included in the
-config/ directory of the tarball package available on the web
-site. Note that these are provided for illustration purposes only and
-may need to be adapted to your particular setup.
-
-The following utility scripts are used by the example action
-scripts (included with ibm-acpi for completeness):
-
-       /usr/local/sbin/idectl -- from the hdparm source distribution,
-               see http://www.ibiblio.org/pub/Linux/system/hardware
-       /usr/local/sbin/laptop_mode -- from the Linux kernel source
-               distribution, see Documentation/laptop-mode.txt
-       /sbin/service -- comes with Redhat/Fedora distributions
-       /usr/sbin/hibernate -- from the Software Suspend 2 distribution,
-               see http://softwaresuspend.berlios.de/
-
-Toan T Nguyen <ntt@physics.ucla.edu> notes that Suse uses the
-powersave program to suspend ('powersave --suspend-to-ram') or
-hibernate ('powersave --suspend-to-disk'). This means that the
-hibernate script is not needed on that distribution.
-
-Henrik Brix Andersen <brix@gentoo.org> has written a Gentoo ACPI event
-handler script for the X31. You can get the latest version from
-http://dev.gentoo.org/~brix/files/x31.sh
-
-David Schweikert <dws@ee.eth.ch> has written an alternative blank.sh
-script which works on Debian systems. This scripts has now been
-extended to also work on Fedora systems and included as the default
-blank.sh in the distribution.
+Commands can also be specified when loading the thinkpad-acpi module,
+for example:
+
+       modprobe thinkpad_acpi hotkey=enable,0xffff video=auto_disable
+
+Enabling debugging output
+-------------------------
+
+The module takes a debug paramater which can be used to selectively
+enable various classes of debugging output, for example:
+
+        modprobe ibm_acpi debug=0xffff
+
+will enable all debugging output classes.  It takes a bitmask, so
+to enable more than one output class, just add their values.
+
+       Debug bitmask           Description
+       0x0001                  Initialization and probing
+       0x0002                  Removal
+
+There is also a kernel build option to enable more debugging
+information, which may be necessary to debug driver problems.
+
+The level of debugging information output by the driver can be changed
+at runtime through sysfs, using the driver attribute debug_level.  The
+attribute takes the same bitmask as the debug module parameter above.
+
+Force loading of module
+-----------------------
+
+If thinkpad-acpi refuses to detect your ThinkPad, you can try to specify
+the module parameter force_load=1.  Regardless of whether this works or
+not, please contact ibm-acpi-devel@lists.sourceforge.net with a report.
+
+
+Sysfs interface changelog:
+
+0x000100:      Initial sysfs support, as a single platform driver and
+               device.
index ecb3416..5e51c59 100644 (file)
@@ -5,10 +5,9 @@ Vaio Picturebook Motion Eye Camera Driver Readme
        Copyright (C) 2000 Andrew Tridgell <tridge@samba.org>
 
 This driver enable the use of video4linux compatible applications with the
-Motion Eye camera. This driver requires the "Sony Vaio Programmable I/O
-Control Device" driver (which can be found in the "Character drivers"
-section of the kernel configuration utility) to be compiled and installed
-(using its "camera=1" parameter).
+Motion Eye camera. This driver requires the "Sony Laptop Extras" driver (which
+can be found in the "Misc devices" section of the kernel configuration utility)
+to be compiled and installed (using its "camera=1" parameter).
 
 It can do at maximum 30 fps @ 320x240 or 15 fps @ 640x480.
 
index 77bff8c..af1c792 100644 (file)
@@ -1582,9 +1582,9 @@ S:        Supported
 
 HOST AP DRIVER
 P:     Jouni Malinen
-M:     jkmaline@cc.hut.fi
+M:     j@w1.fi
+L:     hostap@shmoo.com (subscribers-only)
 L:     linux-wireless@vger.kernel.org
-L:     hostap@shmoo.com
 W:     http://hostap.epitest.fi/
 S:     Maintained
 
@@ -1658,15 +1658,6 @@ W:       http://www.ia64-linux.org/
 T:     git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
 S:     Maintained
 
-IBM ACPI EXTRAS DRIVER
-P:     Henrique de Moraes Holschuh
-M:     ibm-acpi@hmh.eng.br
-L:     ibm-acpi-devel@lists.sourceforge.net
-W:     http://ibm-acpi.sourceforge.net
-W:     http://thinkwiki.org/wiki/Ibm-acpi
-T:     git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
-S:     Maintained
-
 SN-IA64 (Itanium) SUB-PLATFORM
 P:     Jes Sorensen
 M:     jes@sgi.com
@@ -1820,6 +1811,7 @@ P:        Jeff Kirsher
 M:     jeffrey.t.kirsher@intel.com
 P:     Auke Kok
 M:     auke-jan.h.kok@intel.com
+L:     e1000-devel@lists.sourceforge.net
 W:     http://sourceforge.net/projects/e1000/
 S:     Supported
 
@@ -1834,6 +1826,7 @@ P:        Jeff Kirsher
 M:     jeffrey.t.kirsher@intel.com
 P:     Auke Kok
 M:     auke-jan.h.kok@intel.com
+L:     e1000-devel@lists.sourceforge.net
 W:     http://sourceforge.net/projects/e1000/
 S:     Supported
 
@@ -1848,6 +1841,7 @@ P:        Jesse Brandeburg
 M:     jesse.brandeburg@intel.com
 P:     Auke Kok
 M:     auke-jan.h.kok@intel.com
+L:     e1000-devel@lists.sourceforge.net
 W:     http://sourceforge.net/projects/e1000/
 S:     Supported
 
@@ -2509,6 +2503,19 @@ M:       adaplas@gmail.com
 L:     linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
+NETERION (S2IO) Xframe 10GbE DRIVER
+P:     Ramkrishna Vepa
+M:     ram.vepa@neterion.com
+P:     Rastapur Santosh
+M:     santosh.rastapur@neterion.com
+P:     Sivakumar Subramani
+M:     sivakumar.subramani@neterion.com
+P:     Sreenivasa Honnur
+M:     sreenivasa.honnur@neterion.com
+L:     netdev@vger.kernel.org
+W:     http://trac.neterion.com/cgi-bin/trac.cgi/wiki/TitleIndex?anonymous
+S:     Supported
+
 OPENCORES I2C BUS DRIVER
 P:     Peter Korsgaard
 M:     jacmet@sunsite.dk
@@ -3166,6 +3173,15 @@ P:       Chris Zankel
 M:     chris@zankel.net
 S:     Maintained
 
+THINKPAD ACPI EXTRAS DRIVER
+P:     Henrique de Moraes Holschuh
+M:     ibm-acpi@hmh.eng.br
+L:     ibm-acpi-devel@lists.sourceforge.net
+W:     http://ibm-acpi.sourceforge.net
+W:     http://thinkwiki.org/wiki/Ibm-acpi
+T:     git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
+S:     Maintained
+
 UltraSPARC (sparc64):
 P:     David S. Miller
 M:     davem@davemloft.net
index f4efd66..c96911c 100644 (file)
@@ -692,7 +692,6 @@ CONFIG_SATA_SIL=y
 CONFIG_SATA_VIA=y
 # CONFIG_SATA_VITESSE is not set
 # CONFIG_SATA_INIC162X is not set
-CONFIG_SATA_INTEL_COMBINED=y
 CONFIG_SATA_ACPI=y
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
index a7d22d9..8f7efd3 100644 (file)
@@ -23,10 +23,13 @@ static int __init nvidia_hpet_check(struct acpi_table_header *header)
 static int __init check_bridge(int vendor, int device)
 {
 #ifdef CONFIG_ACPI
+       static int warned;
        /* According to Nvidia all timer overrides are bogus unless HPET
           is enabled. */
        if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) {
-               if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check)) {
+               if (!warned && acpi_table_parse(ACPI_SIG_HPET,
+                                               nvidia_hpet_check)) {
+                       warned = 1;
                        acpi_skip_timer_override = 1;
                          printk(KERN_INFO "Nvidia board "
                        "detected. Ignoring ACPI "
index 6aeebc9..dc0bfda 100644 (file)
@@ -17,7 +17,8 @@
 # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
 #
 
-obj-y := sim_setup.o sim_mem.o sim_time.o sim_int.o sim_cmdline.o
+obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o \
+        sim_cmdline.o
 
 obj-$(CONFIG_EARLY_PRINTK) += sim_console.o
 obj-$(CONFIG_SMP) += sim_smp.o
diff --git a/arch/mips/mips-boards/sim/sim_platform.c b/arch/mips/mips-boards/sim/sim_platform.c
new file mode 100644 (file)
index 0000000..53210a8
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 by Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/init.h>
+#include <linux/if_ether.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+static char mipsnet_string[] = "mipsnet";
+
+static struct platform_device eth1_device = {
+       .name           = mipsnet_string,
+       .id             = 0,
+};
+
+/*
+ * Create a platform device for the GPI port that receives the
+ * image data from the embedded camera.
+ */
+static int __init mipsnet_devinit(void)
+{
+       int err;
+
+       err = platform_device_register(&eth1_device);
+       if (err)
+               printk(KERN_ERR "%s: registration failed\n", mipsnet_string);
+
+       return err;
+}
+
+device_initcall(mipsnet_devinit);
index 782906b..eb2f9a3 100644 (file)
@@ -435,7 +435,6 @@ CONFIG_SCSI_SATA_SIL=m
 # CONFIG_SCSI_SATA_ULI is not set
 CONFIG_SCSI_SATA_VIA=m
 # CONFIG_SCSI_SATA_VITESSE is not set
-CONFIG_SCSI_SATA_INTEL_COMBINED=y
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
index a457ac1..66137bf 100644 (file)
@@ -210,6 +210,9 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
        uf_regs = uccf->uf_regs;
        uccf->p_ucce = (u32 *) & (uf_regs->ucce);
        uccf->p_uccm = (u32 *) & (uf_regs->uccm);
+#ifdef CONFIG_UGETH_TX_ON_DEMAND
+       uccf->p_utodr = (u16 *) & (uf_regs->utodr);
+#endif
 #ifdef STATISTICS
        uccf->tx_frames = 0;
        uccf->rx_frames = 0;
index 7a1e251..b263788 100644 (file)
@@ -631,7 +631,6 @@ CONFIG_SATA_SIL=y
 CONFIG_SATA_VIA=y
 # CONFIG_SATA_VITESSE is not set
 # CONFIG_SATA_INIC162X is not set
-CONFIG_SATA_INTEL_COMBINED=y
 CONFIG_SATA_ACPI=y
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
index 094397b..9e917b8 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Michael MIC (IEEE 802.11i/TKIP) keyed digest
  *
- * Copyright (c) 2004 Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2004 Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -173,4 +173,4 @@ module_exit(michael_mic_exit);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Michael MIC");
-MODULE_AUTHOR("Jouni Malinen <jkmaline@cc.hut.fi>");
+MODULE_AUTHOR("Jouni Malinen <j@w1.fi>");
index e2ce4a9..139f41f 100644 (file)
@@ -85,8 +85,8 @@ config ACPI_PROCFS
        depends on ACPI
        default y
        ---help---
-         Procfs interface for ACPI is made optional for back-compatible.
-         As the same functions are duplicated in sysfs interface
+         The Procfs interface for ACPI is made optional for backward compatibility.
+         As the same functions are duplicated in the sysfs interface
          and this proc interface will be removed some time later,
          it's marked as deprecated.
          ( /proc/acpi/debug_layer && debug_level are deprecated by
@@ -218,43 +218,6 @@ config ACPI_ASUS
          NOTE: This driver is deprecated and will probably be removed soon,
          use asus-laptop instead.
 
-config ACPI_IBM
-       tristate "IBM ThinkPad Laptop Extras"
-       depends on X86
-       select BACKLIGHT_CLASS_DEVICE
-       ---help---
-         This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds
-         support for Fn-Fx key combinations, Bluetooth control, video
-         output switching, ThinkLight control, UltraBay eject and more.
-         For more information about this driver see <file:Documentation/ibm-acpi.txt>
-         and <http://ibm-acpi.sf.net/> .
-
-         If you have an IBM ThinkPad laptop, say Y or M here.
-
-config ACPI_IBM_DOCK
-       bool "Legacy Docking Station Support"
-       depends on ACPI_IBM
-       depends on ACPI_DOCK=n
-       default n
-       ---help---
-         Allows the ibm_acpi driver to handle docking station events.
-         This support is obsoleted by CONFIG_HOTPLUG_PCI_ACPI.  It will
-         allow locking and removing the laptop from the docking station,
-         but will not properly connect PCI devices.
-
-         If you are not sure, say N here.
-
-config ACPI_IBM_BAY
-       bool "Legacy Removable Bay Support"
-       depends on ACPI_IBM
-       default y
-       ---help---
-         Allows the ibm_acpi driver to handle removable bays.  It will allow
-         disabling the device in the bay, and also generate notifications when
-         the bay lever is ejected or inserted.
-
-         If you are not sure, say Y here.
-
 config ACPI_TOSHIBA
        tristate "Toshiba Laptop Extras"
        depends on X86
@@ -388,11 +351,10 @@ config ACPI_HOTPLUG_MEMORY
 
 config ACPI_SBS
        tristate "Smart Battery System (EXPERIMENTAL)"
-       depends on X86 && I2C
+       depends on X86
        depends on EXPERIMENTAL
        help
          This driver adds support for the Smart Battery System.
-         Depends on I2C (Device Drivers ---> I2C support)
          A "Smart Battery" is quite old and quite rare compared
          to today's ACPI "Control Method" battery.
 
index 5956e9f..d4336f1 100644 (file)
@@ -1,6 +1,6 @@
 #
 # Makefile for the Linux ACPI interpreter
-# 
+#
 
 export ACPI_CFLAGS
 
@@ -32,16 +32,17 @@ obj-y                               += osl.o utils.o \
 processor-objs += processor_core.o processor_throttling.o \
                                processor_idle.o processor_thermal.o
 ifdef CONFIG_CPU_FREQ
-processor-objs += processor_perflib.o                  
+processor-objs += processor_perflib.o
 endif
 
 obj-y                          += sleep/
 obj-y                          += bus.o glue.o
 obj-y                          += scan.o
+# Keep EC driver first. Initialization of others depend on it.
+obj-$(CONFIG_ACPI_EC)          += ec.o
 obj-$(CONFIG_ACPI_AC)          += ac.o
 obj-$(CONFIG_ACPI_BATTERY)     += battery.o
 obj-$(CONFIG_ACPI_BUTTON)      += button.o
-obj-$(CONFIG_ACPI_EC)          += ec.o
 obj-$(CONFIG_ACPI_FAN)         += fan.o
 obj-$(CONFIG_ACPI_DOCK)                += dock.o
 obj-$(CONFIG_ACPI_BAY)         += bay.o
@@ -55,8 +56,7 @@ obj-$(CONFIG_ACPI_SYSTEM)     += system.o event.o
 obj-$(CONFIG_ACPI_DEBUG)       += debug.o
 obj-$(CONFIG_ACPI_NUMA)                += numa.o
 obj-$(CONFIG_ACPI_ASUS)                += asus_acpi.o
-obj-$(CONFIG_ACPI_IBM)         += ibm_acpi.o
 obj-$(CONFIG_ACPI_TOSHIBA)     += toshiba_acpi.o
 obj-$(CONFIG_ACPI_HOTPLUG_MEMORY)      += acpi_memhotplug.o
 obj-y                          += cm_sbs.o
-obj-$(CONFIG_ACPI_SBS)         += i2c_ec.o sbs.o
+obj-$(CONFIG_ACPI_SBS)         += sbs.o
index c261726..e65628a 100644 (file)
@@ -44,11 +44,6 @@ MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
 MODULE_DESCRIPTION("Hotplug Mem Driver");
 MODULE_LICENSE("GPL");
 
-/* ACPI _STA method values */
-#define ACPI_MEMORY_STA_PRESENT                (0x00000001UL)
-#define ACPI_MEMORY_STA_ENABLED                (0x00000002UL)
-#define ACPI_MEMORY_STA_FUNCTIONAL     (0x00000008UL)
-
 /* Memory Device States */
 #define MEMORY_INVALID_STATE   0
 #define MEMORY_POWER_ON_STATE  1
@@ -204,9 +199,9 @@ static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
         * Check for device status. Device should be
         * present/enabled/functioning.
         */
-       if (!((current_status & ACPI_MEMORY_STA_PRESENT)
-             && (current_status & ACPI_MEMORY_STA_ENABLED)
-             && (current_status & ACPI_MEMORY_STA_FUNCTIONAL)))
+       if (!((current_status & ACPI_STA_DEVICE_PRESENT)
+             && (current_status & ACPI_STA_DEVICE_ENABLED)
+             && (current_status & ACPI_STA_DEVICE_FUNCTIONING)))
                return -ENODEV;
 
        return 0;
@@ -286,7 +281,7 @@ static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
                return -ENODEV;
 
        /* Check for device status.  Device should be disabled */
-       if (current_status & ACPI_MEMORY_STA_ENABLED)
+       if (current_status & ACPI_STA_DEVICE_ENABLED)
                return -EINVAL;
 
        return 0;
index dd49ea0..e5084ec 100644 (file)
@@ -103,7 +103,9 @@ int acpi_bus_get_status(struct acpi_device *device)
        else if (device->parent)
                device->status = device->parent->status;
        else
-               STRUCT_TO_INT(device->status) = 0x0F;
+               STRUCT_TO_INT(device->status) =
+                   ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
+                   ACPI_STA_DEVICE_UI      | ACPI_STA_DEVICE_FUNCTIONING;
 
        if (device->status.functional && !device->status.present) {
                printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: "
index 0930d94..0dd3bf7 100644 (file)
@@ -49,8 +49,6 @@ MODULE_AUTHOR("Anil S Keshavamurthy");
 MODULE_DESCRIPTION("ACPI container driver");
 MODULE_LICENSE("GPL");
 
-#define ACPI_STA_PRESENT               (0x00000001)
-
 static int acpi_container_add(struct acpi_device *device);
 static int acpi_container_remove(struct acpi_device *device, int type);
 
@@ -75,13 +73,13 @@ static int is_device_present(acpi_handle handle)
 
        status = acpi_get_handle(handle, "_STA", &temp);
        if (ACPI_FAILURE(status))
-               return 1;       /* _STA not found, assmue device present */
+               return 1;       /* _STA not found, assume device present */
 
        status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
        if (ACPI_FAILURE(status))
                return 0;       /* Firmware error */
 
-       return ((sta & ACPI_STA_PRESENT) == ACPI_STA_PRESENT);
+       return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
 }
 
 /*******************************************************************/
index 54a697f..4546bf8 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/notifier.h>
 #include <linux/platform_device.h>
 #include <linux/jiffies.h>
+#include <linux/stddef.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -667,6 +668,23 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
 }
 DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
 
+/*
+ * show_dock_uid - read method for "uid" file in sysfs
+ */
+static ssize_t show_dock_uid(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       unsigned long lbuf;
+       acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf);
+       if(ACPI_FAILURE(status)) {
+           return 0;
+       }
+       return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
+}
+DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
+
+
+
 /**
  * dock_add - add a new dock station
  * @handle: the dock station handle
@@ -715,6 +733,13 @@ static int dock_add(acpi_handle handle)
                kfree(dock_station);
                return ret;
        }
+       ret = device_create_file(&dock_device.dev, &dev_attr_uid);
+       if (ret) {
+               printk("Error %d adding sysfs file\n", ret);
+               platform_device_unregister(&dock_device);
+               kfree(dock_station);
+               return ret;
+       }
 
        /* Find dependent devices */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
index a802962..e08cf98 100644 (file)
@@ -1,6 +1,8 @@
 /*
- *  acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 38 $)
+ *  ec.c - ACPI Embedded Controller Driver (v2.0)
  *
+ *  Copyright (C) 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
+ *  Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com>
  *  Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -91,9 +93,9 @@ static struct acpi_driver acpi_ec_driver = {
 };
 
 /* If we find an EC via the ECDT, we need to keep a ptr to its context */
+/* External interfaces use first EC only, so remember */
 static struct acpi_ec {
        acpi_handle handle;
-       unsigned long uid;
        unsigned long gpe;
        unsigned long command_addr;
        unsigned long data_addr;
@@ -101,12 +103,8 @@ static struct acpi_ec {
        struct mutex lock;
        atomic_t query_pending;
        atomic_t event_count;
-       atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
        wait_queue_head_t wait;
-} *ec_ecdt;
-
-/* External interfaces use first EC only, so remember */
-static struct acpi_device *first_ec;
+} *boot_ec, *first_ec;
 
 /* --------------------------------------------------------------------------
                              Transaction Management
@@ -173,56 +171,6 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count)
        return -ETIME;
 }
 
-#ifdef ACPI_FUTURE_USAGE
-/*
- * Note: samsung nv5000 doesn't work with ec burst mode.
- * http://bugzilla.kernel.org/show_bug.cgi?id=4980
- */
-int acpi_ec_enter_burst_mode(struct acpi_ec *ec)
-{
-       u8 tmp = 0;
-       u8 status = 0;
-
-       status = acpi_ec_read_status(ec);
-       if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) {
-               status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
-               if (status)
-                       goto end;
-               acpi_ec_write_cmd(ec, ACPI_EC_BURST_ENABLE);
-               status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1);
-               tmp = acpi_ec_read_data(ec);
-               if (tmp != 0x90) {      /* Burst ACK byte */
-                       return -EINVAL;
-               }
-       }
-
-       atomic_set(&ec->leaving_burst, 0);
-       return 0;
-      end:
-       ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode"));
-       return -1;
-}
-
-int acpi_ec_leave_burst_mode(struct acpi_ec *ec)
-{
-       u8 status = 0;
-
-       status = acpi_ec_read_status(ec);
-       if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)) {
-               status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
-               if (status)
-                       goto end;
-               acpi_ec_write_cmd(ec, ACPI_EC_BURST_DISABLE);
-               acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
-       }
-       atomic_set(&ec->leaving_burst, 1);
-       return 0;
-      end:
-       ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode"));
-       return -1;
-}
-#endif                         /* ACPI_FUTURE_USAGE */
-
 static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
                                        const u8 * wdata, unsigned wdata_len,
                                        u8 * rdata, unsigned rdata_len)
@@ -312,6 +260,21 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
        return status;
 }
 
+/*
+ * Note: samsung nv5000 doesn't work with ec burst mode.
+ * http://bugzilla.kernel.org/show_bug.cgi?id=4980
+ */
+int acpi_ec_burst_enable(struct acpi_ec *ec)
+{
+       u8 d;
+       return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1);
+}
+
+int acpi_ec_burst_disable(struct acpi_ec *ec)
+{
+       return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0);
+}
+
 static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
 {
        int result;
@@ -333,18 +296,33 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
 /*
  * Externally callable EC access functions. For now, assume 1 EC only
  */
+int ec_burst_enable(void)
+{
+       if (!first_ec)
+               return -ENODEV;
+       return acpi_ec_burst_enable(first_ec);
+}
+
+EXPORT_SYMBOL(ec_burst_enable);
+
+int ec_burst_disable(void)
+{
+       if (!first_ec)
+               return -ENODEV;
+       return acpi_ec_burst_disable(first_ec);
+}
+
+EXPORT_SYMBOL(ec_burst_disable);
+
 int ec_read(u8 addr, u8 * val)
 {
-       struct acpi_ec *ec;
        int err;
        u8 temp_data;
 
        if (!first_ec)
                return -ENODEV;
 
-       ec = acpi_driver_data(first_ec);
-
-       err = acpi_ec_read(ec, addr, &temp_data);
+       err = acpi_ec_read(first_ec, addr, &temp_data);
 
        if (!err) {
                *val = temp_data;
@@ -357,15 +335,12 @@ EXPORT_SYMBOL(ec_read);
 
 int ec_write(u8 addr, u8 val)
 {
-       struct acpi_ec *ec;
        int err;
 
        if (!first_ec)
                return -ENODEV;
 
-       ec = acpi_driver_data(first_ec);
-
-       err = acpi_ec_write(ec, addr, val);
+       err = acpi_ec_write(first_ec, addr, val);
 
        return err;
 }
@@ -376,14 +351,10 @@ int ec_transaction(u8 command,
                   const u8 * wdata, unsigned wdata_len,
                   u8 * rdata, unsigned rdata_len)
 {
-       struct acpi_ec *ec;
-
        if (!first_ec)
                return -ENODEV;
 
-       ec = acpi_driver_data(first_ec);
-
-       return acpi_ec_transaction(ec, command, wdata,
+       return acpi_ec_transaction(first_ec, command, wdata,
                                   wdata_len, rdata, rdata_len);
 }
 
@@ -420,7 +391,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
 
 static void acpi_ec_gpe_query(void *ec_cxt)
 {
-       struct acpi_ec *ec = (struct acpi_ec *)ec_cxt;
+       struct acpi_ec *ec = ec_cxt;
        u8 value = 0;
        char object_name[8];
 
@@ -438,8 +409,9 @@ static u32 acpi_ec_gpe_handler(void *data)
 {
        acpi_status status = AE_OK;
        u8 value;
-       struct acpi_ec *ec = (struct acpi_ec *)data;
+       struct acpi_ec *ec = data;
        atomic_inc(&ec->event_count);
+
        if (acpi_ec_mode == EC_INTR) {
                wake_up(&ec->wait);
        }
@@ -482,7 +454,7 @@ acpi_ec_space_handler(u32 function,
                      void *handler_context, void *region_context)
 {
        int result = 0;
-       struct acpi_ec *ec = NULL;
+       struct acpi_ec *ec = handler_context;
        u64 temp = *value;
        acpi_integer f_v = 0;
        int i = 0;
@@ -494,8 +466,6 @@ acpi_ec_space_handler(u32 function,
                return AE_BAD_PARAMETER;
        }
 
-       ec = (struct acpi_ec *)handler_context;
-
       next_byte:
        switch (function) {
        case ACPI_READ:
@@ -551,18 +521,16 @@ static struct proc_dir_entry *acpi_ec_dir;
 
 static int acpi_ec_read_info(struct seq_file *seq, void *offset)
 {
-       struct acpi_ec *ec = (struct acpi_ec *)seq->private;
+       struct acpi_ec *ec = seq->private;
 
        if (!ec)
                goto end;
 
-       seq_printf(seq, "gpe:                 0x%02x\n", (u32) ec->gpe);
-       seq_printf(seq, "ports:                   0x%02x, 0x%02x\n",
-                  (u32) ec->command_addr, (u32) ec->data_addr);
-       seq_printf(seq, "use global lock:         %s\n",
+       seq_printf(seq, "gpe:\t\t\t0x%02x\n", (u32) ec->gpe);
+       seq_printf(seq, "ports:\t\t\t0x%02x, 0x%02x\n",
+                  (unsigned)ec->command_addr, (unsigned)ec->data_addr);
+       seq_printf(seq, "use global lock:\t%s\n",
                   ec->global_lock ? "yes" : "no");
-       acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
-
       end:
        return 0;
 }
@@ -619,154 +587,122 @@ static int acpi_ec_remove_fs(struct acpi_device *device)
 /* --------------------------------------------------------------------------
                                Driver Interface
    -------------------------------------------------------------------------- */
+static acpi_status
+ec_parse_io_ports(struct acpi_resource *resource, void *context);
+
+static acpi_status
+ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval);
+
+static struct acpi_ec *make_acpi_ec(void)
+{
+       struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+       if (!ec)
+               return NULL;
+
+       atomic_set(&ec->query_pending, 1);
+       atomic_set(&ec->event_count, 1);
+       mutex_init(&ec->lock);
+       init_waitqueue_head(&ec->wait);
+
+       return ec;
+}
 
 static int acpi_ec_add(struct acpi_device *device)
 {
-       int result = 0;
        acpi_status status = AE_OK;
        struct acpi_ec *ec = NULL;
 
        if (!device)
                return -EINVAL;
 
-       ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
-       if (!ec)
-               return -ENOMEM;
-
-       ec->handle = device->handle;
-       ec->uid = -1;
-       mutex_init(&ec->lock);
-       atomic_set(&ec->query_pending, 0);
-       atomic_set(&ec->event_count, 1);
-       if (acpi_ec_mode == EC_INTR) {
-               atomic_set(&ec->leaving_burst, 1);
-               init_waitqueue_head(&ec->wait);
-       }
        strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_EC_CLASS);
-       acpi_driver_data(device) = ec;
-
-       /* Use the global lock for all EC transactions? */
-       acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock);
-
-       /* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
-          http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
-       if (ec_ecdt) {
-               acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
-                                                 ACPI_ADR_SPACE_EC,
-                                                 &acpi_ec_space_handler);
 
-               acpi_remove_gpe_handler(NULL, ec_ecdt->gpe,
-                                       &acpi_ec_gpe_handler);
+       ec = make_acpi_ec();
+       if (!ec)
+               return -ENOMEM;
 
-               kfree(ec_ecdt);
+       status = ec_parse_device(device->handle, 0, ec, NULL);
+       if (status != AE_CTRL_TERMINATE) {
+               kfree(ec);
+               return -EINVAL;
        }
 
-       /* Get GPE bit assignment (EC events). */
-       /* TODO: Add support for _GPE returning a package */
-       status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe);
-       if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status,
-                               "Obtaining GPE bit assignment"));
-               result = -ENODEV;
-               goto end;
-       }
+       /* Check if we found the boot EC */
+       if (boot_ec) {
+               if (boot_ec->gpe == ec->gpe) {
+                       /* We might have incorrect info for GL at boot time */
+                       mutex_lock(&boot_ec->lock);
+                       boot_ec->global_lock = ec->global_lock;
+                       mutex_unlock(&boot_ec->lock);
+                       kfree(ec);
+                       ec = boot_ec;
+               }
+       } else
+               first_ec = ec;
+       ec->handle = device->handle;
+       acpi_driver_data(device) = ec;
 
-       result = acpi_ec_add_fs(device);
-       if (result)
-               goto end;
+       acpi_ec_add_fs(device);
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.",
                          acpi_device_name(device), acpi_device_bid(device),
                          (u32) ec->gpe));
 
-       if (!first_ec)
-               first_ec = device;
-
-      end:
-       if (result)
-               kfree(ec);
-
-       return result;
+       return 0;
 }
 
 static int acpi_ec_remove(struct acpi_device *device, int type)
 {
-       struct acpi_ec *ec = NULL;
+       struct acpi_ec *ec;
 
        if (!device)
                return -EINVAL;
 
        ec = acpi_driver_data(device);
-
        acpi_ec_remove_fs(device);
+       acpi_driver_data(device) = NULL;
+       if (ec == first_ec)
+               first_ec = NULL;
 
-       kfree(ec);
-
+       /* Don't touch boot EC */
+       if (boot_ec != ec)
+               kfree(ec);
        return 0;
 }
 
 static acpi_status
-acpi_ec_io_ports(struct acpi_resource *resource, void *context)
+ec_parse_io_ports(struct acpi_resource *resource, void *context)
 {
-       struct acpi_ec *ec = (struct acpi_ec *)context;
+       struct acpi_ec *ec = context;
 
-       if (resource->type != ACPI_RESOURCE_TYPE_IO) {
+       if (resource->type != ACPI_RESOURCE_TYPE_IO)
                return AE_OK;
-       }
 
        /*
         * The first address region returned is the data port, and
         * the second address region returned is the status/command
         * port.
         */
-       if (ec->data_addr == 0) {
+       if (ec->data_addr == 0)
                ec->data_addr = resource->data.io.minimum;
-       } else if (ec->command_addr == 0) {
+       else if (ec->command_addr == 0)
                ec->command_addr = resource->data.io.minimum;
-       } else {
+       else
                return AE_CTRL_TERMINATE;
-       }
 
        return AE_OK;
 }
 
-static int acpi_ec_start(struct acpi_device *device)
+static int ec_install_handlers(struct acpi_ec *ec)
 {
-       acpi_status status = AE_OK;
-       struct acpi_ec *ec = NULL;
-
-       if (!device)
-               return -EINVAL;
-
-       ec = acpi_driver_data(device);
-
-       if (!ec)
-               return -EINVAL;
-
-       /*
-        * Get I/O port addresses. Convert to GAS format.
-        */
-       status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS,
-                                    acpi_ec_io_ports, ec);
-       if (ACPI_FAILURE(status) || ec->command_addr == 0) {
-               ACPI_EXCEPTION((AE_INFO, status,
-                               "Error getting I/O port addresses"));
-               return -ENODEV;
-       }
-
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
-                         ec->gpe, ec->command_addr, ec->data_addr));
-
-       /*
-        * Install GPE handler
-        */
+       acpi_status status;
        status = acpi_install_gpe_handler(NULL, ec->gpe,
                                          ACPI_GPE_EDGE_TRIGGERED,
                                          &acpi_ec_gpe_handler, ec);
-       if (ACPI_FAILURE(status)) {
+       if (ACPI_FAILURE(status))
                return -ENODEV;
-       }
+
        acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
        acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
 
@@ -779,18 +715,49 @@ static int acpi_ec_start(struct acpi_device *device)
                return -ENODEV;
        }
 
-       return AE_OK;
+       /* EC is fully operational, allow queries */
+       atomic_set(&ec->query_pending, 0);
+
+       return 0;
+}
+
+static int acpi_ec_start(struct acpi_device *device)
+{
+       struct acpi_ec *ec;
+
+       if (!device)
+               return -EINVAL;
+
+       ec = acpi_driver_data(device);
+
+       if (!ec)
+               return -EINVAL;
+
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
+                         ec->gpe, ec->command_addr, ec->data_addr));
+
+       /* Boot EC is already working */
+       if (ec == boot_ec)
+               return 0;
+
+       return ec_install_handlers(ec);
 }
 
 static int acpi_ec_stop(struct acpi_device *device, int type)
 {
-       acpi_status status = AE_OK;
-       struct acpi_ec *ec = NULL;
+       acpi_status status;
+       struct acpi_ec *ec;
 
        if (!device)
                return -EINVAL;
 
        ec = acpi_driver_data(device);
+       if (!ec)
+               return -EINVAL;
+
+       /* Don't touch boot EC */
+       if (ec == boot_ec)
+               return 0;
 
        status = acpi_remove_address_space_handler(ec->handle,
                                                   ACPI_ADR_SPACE_EC,
@@ -805,164 +772,67 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
        return 0;
 }
 
-static acpi_status __init
-acpi_fake_ecdt_callback(acpi_handle handle,
-                       u32 Level, void *context, void **retval)
+static acpi_status
+ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
 {
        acpi_status status;
 
-       mutex_init(&ec_ecdt->lock);
-       atomic_set(&ec_ecdt->event_count, 1);
-       if (acpi_ec_mode == EC_INTR) {
-               init_waitqueue_head(&ec_ecdt->wait);
-       }
+       struct acpi_ec *ec = context;
        status = acpi_walk_resources(handle, METHOD_NAME__CRS,
-                                    acpi_ec_io_ports, ec_ecdt);
+                                    ec_parse_io_ports, ec);
        if (ACPI_FAILURE(status))
                return status;
 
-       ec_ecdt->uid = -1;
-       acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid);
-
-       status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe);
+       /* Get GPE bit assignment (EC events). */
+       /* TODO: Add support for _GPE returning a package */
+       status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
        if (ACPI_FAILURE(status))
                return status;
-       ec_ecdt->global_lock = TRUE;
-       ec_ecdt->handle = handle;
-
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
-                         ec_ecdt->gpe, ec_ecdt->command_addr,
-                         ec_ecdt->data_addr));
 
-       return AE_CTRL_TERMINATE;
-}
-
-/*
- * Some BIOS (such as some from Gateway laptops) access EC region very early
- * such as in BAT0._INI or EC._INI before an EC device is found and
- * do not provide an ECDT. According to ACPI spec, ECDT isn't mandatorily
- * required, but if EC regison is accessed early, it is required.
- * The routine tries to workaround the BIOS bug by pre-scan EC device
- * It assumes that _CRS, _HID, _GPE, _UID methods of EC don't touch any
- * op region (since _REG isn't invoked yet). The assumption is true for
- * all systems found.
- */
-static int __init acpi_ec_fake_ecdt(void)
-{
-       acpi_status status;
-       int ret = 0;
+       /* Use the global lock for all EC transactions? */
+       acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
 
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Try to make an fake ECDT"));
+       ec->handle = handle;
 
-       ec_ecdt = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
-       if (!ec_ecdt) {
-               ret = -ENOMEM;
-               goto error;
-       }
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
+                         ec->gpe, ec->command_addr, ec->data_addr));
 
-       status = acpi_get_devices(ACPI_EC_HID,
-                                 acpi_fake_ecdt_callback, NULL, NULL);
-       if (ACPI_FAILURE(status)) {
-               kfree(ec_ecdt);
-               ec_ecdt = NULL;
-               ret = -ENODEV;
-               ACPI_EXCEPTION((AE_INFO, status, "Can't make an fake ECDT"));
-               goto error;
-       }
-       return 0;
-      error:
-       return ret;
+       return AE_CTRL_TERMINATE;
 }
 
-static int __init acpi_ec_get_real_ecdt(void)
+int __init acpi_ec_ecdt_probe(void)
 {
+       int ret;
        acpi_status status;
        struct acpi_table_ecdt *ecdt_ptr;
 
-       status = acpi_get_table(ACPI_SIG_ECDT, 1,
-                               (struct acpi_table_header **)&ecdt_ptr);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
-
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT"));
-
+       boot_ec = make_acpi_ec();
+       if (!boot_ec)
+               return -ENOMEM;
        /*
-        * Generate a temporary ec context to use until the namespace is scanned
+        * Generate a boot ec context
         */
-       ec_ecdt = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
-       if (!ec_ecdt)
-               return -ENOMEM;
 
-       mutex_init(&ec_ecdt->lock);
-       atomic_set(&ec_ecdt->event_count, 1);
-       if (acpi_ec_mode == EC_INTR) {
-               init_waitqueue_head(&ec_ecdt->wait);
-       }
-       ec_ecdt->command_addr = ecdt_ptr->control.address;
-       ec_ecdt->data_addr = ecdt_ptr->data.address;
-       ec_ecdt->gpe = ecdt_ptr->gpe;
-       /* use the GL just to be safe */
-       ec_ecdt->global_lock = TRUE;
-       ec_ecdt->uid = ecdt_ptr->uid;
-
-       status = acpi_get_handle(NULL, ecdt_ptr->id, &ec_ecdt->handle);
-       if (ACPI_FAILURE(status)) {
+       status = acpi_get_table(ACPI_SIG_ECDT, 1,
+                               (struct acpi_table_header **)&ecdt_ptr);
+       if (ACPI_FAILURE(status))
                goto error;
-       }
-
-       return 0;
-      error:
-       ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT"));
-       kfree(ec_ecdt);
-       ec_ecdt = NULL;
 
-       return -ENODEV;
-}
-
-static int __initdata acpi_fake_ecdt_enabled;
-int __init acpi_ec_ecdt_probe(void)
-{
-       acpi_status status;
-       int ret;
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT"));
 
-       ret = acpi_ec_get_real_ecdt();
-       /* Try to make a fake ECDT */
-       if (ret && acpi_fake_ecdt_enabled) {
-               ret = acpi_ec_fake_ecdt();
-       }
+       boot_ec->command_addr = ecdt_ptr->control.address;
+       boot_ec->data_addr = ecdt_ptr->data.address;
+       boot_ec->gpe = ecdt_ptr->gpe;
+       boot_ec->handle = ACPI_ROOT_OBJECT;
 
-       if (ret)
+       ret = ec_install_handlers(boot_ec);
+       if (!ret) {
+               first_ec = boot_ec;
                return 0;
-
-       /*
-        * Install GPE handler
-        */
-       status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe,
-                                         ACPI_GPE_EDGE_TRIGGERED,
-                                         &acpi_ec_gpe_handler, ec_ecdt);
-       if (ACPI_FAILURE(status)) {
-               goto error;
        }
-       acpi_set_gpe_type(NULL, ec_ecdt->gpe, ACPI_GPE_TYPE_RUNTIME);
-       acpi_enable_gpe(NULL, ec_ecdt->gpe, ACPI_NOT_ISR);
-
-       status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
-                                                   ACPI_ADR_SPACE_EC,
-                                                   &acpi_ec_space_handler,
-                                                   &acpi_ec_space_setup,
-                                                   ec_ecdt);
-       if (ACPI_FAILURE(status)) {
-               acpi_remove_gpe_handler(NULL, ec_ecdt->gpe,
-                                       &acpi_ec_gpe_handler);
-               goto error;
-       }
-
-       return 0;
-
       error:
-       ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT"));
-       kfree(ec_ecdt);
-       ec_ecdt = NULL;
+       kfree(boot_ec);
+       boot_ec = NULL;
 
        return -ENODEV;
 }
@@ -1003,13 +873,6 @@ static void __exit acpi_ec_exit(void)
 }
 #endif                         /* 0 */
 
-static int __init acpi_fake_ecdt_setup(char *str)
-{
-       acpi_fake_ecdt_enabled = 1;
-       return 1;
-}
-
-__setup("acpi_fake_ecdt", acpi_fake_ecdt_setup);
 static int __init acpi_ec_set_intr_mode(char *str)
 {
        int intr;
@@ -1017,12 +880,8 @@ static int __init acpi_ec_set_intr_mode(char *str)
        if (!get_option(&str, &intr))
                return 0;
 
-       if (intr) {
-               acpi_ec_mode = EC_INTR;
-       } else {
-               acpi_ec_mode = EC_POLL;
-       }
-       acpi_ec_driver.ops.add = acpi_ec_add;
+       acpi_ec_mode = (intr) ? EC_INTR : EC_POLL;
+
        printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling");
 
        return 1;
diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c
deleted file mode 100644 (file)
index acab4a4..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * SMBus driver for ACPI Embedded Controller ($Revision: 1.3 $)
- *
- * Copyright (c) 2002, 2005 Ducrot Bruno
- * Copyright (c) 2005 Rich Townsend (tiny hacks & tweaks)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2.
- */
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/acpi.h>
-#include <linux/delay.h>
-
-#include "i2c_ec.h"
-
-#define        xudelay(t)      udelay(t)
-#define        xmsleep(t)      msleep(t)
-
-#define ACPI_EC_HC_COMPONENT   0x00080000
-#define ACPI_EC_HC_CLASS       "ec_hc_smbus"
-#define ACPI_EC_HC_HID         "ACPI0001"
-#define ACPI_EC_HC_DEVICE_NAME "EC HC smbus"
-
-#define _COMPONENT             ACPI_EC_HC_COMPONENT
-
-ACPI_MODULE_NAME("i2c_ec");
-
-static int acpi_ec_hc_add(struct acpi_device *device);
-static int acpi_ec_hc_remove(struct acpi_device *device, int type);
-
-static struct acpi_driver acpi_ec_hc_driver = {
-       .name = "i2c_ec",
-       .class = ACPI_EC_HC_CLASS,
-       .ids = ACPI_EC_HC_HID,
-       .ops = {
-               .add = acpi_ec_hc_add,
-               .remove = acpi_ec_hc_remove,
-               },
-};
-
-/* Various bit mask for EC_SC (R) */
-#define OBF            0x01
-#define IBF            0x02
-#define CMD            0x08
-#define BURST          0x10
-#define SCI_EVT                0x20
-#define SMI_EVT                0x40
-
-/* Commands for EC_SC (W) */
-#define RD_EC          0x80
-#define WR_EC          0x81
-#define BE_EC          0x82
-#define BD_EC          0x83
-#define QR_EC          0x84
-
-/*
- * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
- */
-
-#define ACPI_EC_SMB_PRTCL      0x00    /* protocol, PEC */
-#define ACPI_EC_SMB_STS                0x01    /* status */
-#define ACPI_EC_SMB_ADDR       0x02    /* address */
-#define ACPI_EC_SMB_CMD                0x03    /* command */
-#define ACPI_EC_SMB_DATA       0x04    /* 32 data registers */
-#define ACPI_EC_SMB_BCNT       0x24    /* number of data bytes */
-#define ACPI_EC_SMB_ALRM_A     0x25    /* alarm address */
-#define ACPI_EC_SMB_ALRM_D     0x26    /* 2 bytes alarm data */
-
-#define ACPI_EC_SMB_STS_DONE   0x80
-#define ACPI_EC_SMB_STS_ALRM   0x40
-#define ACPI_EC_SMB_STS_RES    0x20
-#define ACPI_EC_SMB_STS_STATUS 0x1f
-
-#define ACPI_EC_SMB_STATUS_OK          0x00
-#define ACPI_EC_SMB_STATUS_FAIL                0x07
-#define ACPI_EC_SMB_STATUS_DNAK                0x10
-#define ACPI_EC_SMB_STATUS_DERR                0x11
-#define ACPI_EC_SMB_STATUS_CMD_DENY    0x12
-#define ACPI_EC_SMB_STATUS_UNKNOWN     0x13
-#define ACPI_EC_SMB_STATUS_ACC_DENY    0x17
-#define ACPI_EC_SMB_STATUS_TIMEOUT     0x18
-#define ACPI_EC_SMB_STATUS_NOTSUP      0x19
-#define ACPI_EC_SMB_STATUS_BUSY                0x1A
-#define ACPI_EC_SMB_STATUS_PEC         0x1F
-
-#define ACPI_EC_SMB_PRTCL_WRITE                        0x00
-#define ACPI_EC_SMB_PRTCL_READ                 0x01
-#define ACPI_EC_SMB_PRTCL_QUICK                        0x02
-#define ACPI_EC_SMB_PRTCL_BYTE                 0x04
-#define ACPI_EC_SMB_PRTCL_BYTE_DATA            0x06
-#define ACPI_EC_SMB_PRTCL_WORD_DATA            0x08
-#define ACPI_EC_SMB_PRTCL_BLOCK_DATA           0x0a
-#define ACPI_EC_SMB_PRTCL_PROC_CALL            0x0c
-#define ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL      0x0d
-#define ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA       0x4a
-#define ACPI_EC_SMB_PRTCL_PEC                  0x80
-
-/* Length of pre/post transaction sleep (msec) */
-#define ACPI_EC_SMB_TRANSACTION_SLEEP          1
-#define ACPI_EC_SMB_ACCESS_SLEEP1              1
-#define ACPI_EC_SMB_ACCESS_SLEEP2              10
-
-static int acpi_ec_smb_read(struct acpi_ec_smbus *smbus, u8 address, u8 * data)
-{
-       u8 val;
-       int err;
-
-       err = ec_read(smbus->base + address, &val);
-       if (!err) {
-               *data = val;
-       }
-       xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP);
-       return (err);
-}
-
-static int acpi_ec_smb_write(struct acpi_ec_smbus *smbus, u8 address, u8 data)
-{
-       int err;
-
-       err = ec_write(smbus->base + address, data);
-       return (err);
-}
-
-static int
-acpi_ec_smb_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
-                  char read_write, u8 command, int size,
-                  union i2c_smbus_data *data)
-{
-       struct acpi_ec_smbus *smbus = adap->algo_data;
-       unsigned char protocol, len = 0, pec, temp[2] = { 0, 0 };
-       int i;
-
-       if (read_write == I2C_SMBUS_READ) {
-               protocol = ACPI_EC_SMB_PRTCL_READ;
-       } else {
-               protocol = ACPI_EC_SMB_PRTCL_WRITE;
-       }
-       pec = (flags & I2C_CLIENT_PEC) ? ACPI_EC_SMB_PRTCL_PEC : 0;
-
-       switch (size) {
-
-       case I2C_SMBUS_QUICK:
-               protocol |= ACPI_EC_SMB_PRTCL_QUICK;
-               read_write = I2C_SMBUS_WRITE;
-               break;
-
-       case I2C_SMBUS_BYTE:
-               if (read_write == I2C_SMBUS_WRITE) {
-                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte);
-               }
-               protocol |= ACPI_EC_SMB_PRTCL_BYTE;
-               break;
-
-       case I2C_SMBUS_BYTE_DATA:
-               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
-               if (read_write == I2C_SMBUS_WRITE) {
-                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte);
-               }
-               protocol |= ACPI_EC_SMB_PRTCL_BYTE_DATA;
-               break;
-
-       case I2C_SMBUS_WORD_DATA:
-               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
-               if (read_write == I2C_SMBUS_WRITE) {
-                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word);
-                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1,
-                                         data->word >> 8);
-               }
-               protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA | pec;
-               break;
-
-       case I2C_SMBUS_BLOCK_DATA:
-               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
-               if (read_write == I2C_SMBUS_WRITE) {
-                       len = min_t(u8, data->block[0], 32);
-                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
-                       for (i = 0; i < len; i++)
-                               acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
-                                                 data->block[i + 1]);
-               }
-               protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA | pec;
-               break;
-
-       case I2C_SMBUS_I2C_BLOCK_DATA:
-               len = min_t(u8, data->block[0], 32);
-               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
-               acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
-               if (read_write == I2C_SMBUS_WRITE) {
-                       for (i = 0; i < len; i++) {
-                               acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
-                                                 data->block[i + 1]);
-                       }
-               }
-               protocol |= ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA;
-               break;
-
-       case I2C_SMBUS_PROC_CALL:
-               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
-               acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word);
-               acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1, data->word >> 8);
-               protocol = ACPI_EC_SMB_PRTCL_PROC_CALL | pec;
-               read_write = I2C_SMBUS_READ;
-               break;
-
-       case I2C_SMBUS_BLOCK_PROC_CALL:
-               protocol |= pec;
-               len = min_t(u8, data->block[0], 31);
-               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
-               acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
-               for (i = 0; i < len; i++)
-                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
-                                         data->block[i + 1]);
-               protocol = ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL | pec;
-               read_write = I2C_SMBUS_READ;
-               break;
-
-       default:
-               ACPI_DEBUG_PRINT((ACPI_DB_WARN, "EC SMBus adapter: "
-                                 "Unsupported transaction %d\n", size));
-               return (-1);
-       }
-
-       acpi_ec_smb_write(smbus, ACPI_EC_SMB_ADDR, addr << 1);
-       acpi_ec_smb_write(smbus, ACPI_EC_SMB_PRTCL, protocol);
-
-       acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
-
-       if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
-               xudelay(500);
-               acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
-       }
-       if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
-               xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2);
-               acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
-       }
-       if ((~temp[0] & ACPI_EC_SMB_STS_DONE)
-           || (temp[0] & ACPI_EC_SMB_STS_STATUS)) {
-               return (-1);
-       }
-
-       if (read_write == I2C_SMBUS_WRITE) {
-               return (0);
-       }
-
-       switch (size) {
-
-       case I2C_SMBUS_BYTE:
-       case I2C_SMBUS_BYTE_DATA:
-               acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, &data->byte);
-               break;
-
-       case I2C_SMBUS_WORD_DATA:
-       case I2C_SMBUS_PROC_CALL:
-               acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, temp + 0);
-               acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + 1, temp + 1);
-               data->word = (temp[1] << 8) | temp[0];
-               break;
-
-       case I2C_SMBUS_BLOCK_DATA:
-       case I2C_SMBUS_BLOCK_PROC_CALL:
-               len = 0;
-               acpi_ec_smb_read(smbus, ACPI_EC_SMB_BCNT, &len);
-               len = min_t(u8, len, 32);
-       case I2C_SMBUS_I2C_BLOCK_DATA:
-               for (i = 0; i < len; i++)
-                       acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + i,
-                                        data->block + i + 1);
-               data->block[0] = len;
-               break;
-       }
-
-       return (0);
-}
-
-static u32 acpi_ec_smb_func(struct i2c_adapter *adapter)
-{
-
-       return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
-               I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
-               I2C_FUNC_SMBUS_BLOCK_DATA |
-               I2C_FUNC_SMBUS_PROC_CALL |
-               I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
-               I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC);
-}
-
-static const struct i2c_algorithm acpi_ec_smbus_algorithm = {
-       .smbus_xfer = acpi_ec_smb_access,
-       .functionality = acpi_ec_smb_func,
-};
-
-static int acpi_ec_hc_add(struct acpi_device *device)
-{
-       int status;
-       unsigned long val;
-       struct acpi_ec_hc *ec_hc;
-       struct acpi_ec_smbus *smbus;
-
-       if (!device) {
-               return -EINVAL;
-       }
-
-       ec_hc = kzalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL);
-       if (!ec_hc) {
-               return -ENOMEM;
-       }
-
-       smbus = kzalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL);
-       if (!smbus) {
-               kfree(ec_hc);
-               return -ENOMEM;
-       }
-
-       ec_hc->handle = device->handle;
-       strcpy(acpi_device_name(device), ACPI_EC_HC_DEVICE_NAME);
-       strcpy(acpi_device_class(device), ACPI_EC_HC_CLASS);
-       acpi_driver_data(device) = ec_hc;
-
-       status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val);
-       if (ACPI_FAILURE(status)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n"));
-               kfree(ec_hc);
-               kfree(smbus);
-               return -EIO;
-       }
-
-       smbus->ec = acpi_driver_data(device->parent);
-       smbus->base = (val & 0xff00ull) >> 8;
-       smbus->alert = val & 0xffull;
-
-       smbus->adapter.owner = THIS_MODULE;
-       smbus->adapter.algo = &acpi_ec_smbus_algorithm;
-       smbus->adapter.algo_data = smbus;
-       smbus->adapter.dev.parent = &device->dev;
-
-       if (i2c_add_adapter(&smbus->adapter)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-                                 "EC SMBus adapter: Failed to register adapter\n"));
-               kfree(smbus);
-               kfree(ec_hc);
-               return -EIO;
-       }
-
-       ec_hc->smbus = smbus;
-
-       printk(KERN_INFO PREFIX "%s [%s]\n",
-              acpi_device_name(device), acpi_device_bid(device));
-
-       return AE_OK;
-}
-
-static int acpi_ec_hc_remove(struct acpi_device *device, int type)
-{
-       struct acpi_ec_hc *ec_hc;
-
-       if (!device) {
-               return -EINVAL;
-       }
-       ec_hc = acpi_driver_data(device);
-
-       i2c_del_adapter(&ec_hc->smbus->adapter);
-       kfree(ec_hc->smbus);
-       kfree(ec_hc);
-
-       return AE_OK;
-}
-
-static int __init acpi_ec_hc_init(void)
-{
-       int result;
-
-       result = acpi_bus_register_driver(&acpi_ec_hc_driver);
-       if (result < 0) {
-               return -ENODEV;
-       }
-       return 0;
-}
-
-static void __exit acpi_ec_hc_exit(void)
-{
-       acpi_bus_unregister_driver(&acpi_ec_hc_driver);
-}
-
-struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device)
-{
-       return acpi_driver_data(device->parent);
-}
-
-EXPORT_SYMBOL(acpi_get_ec_hc);
-
-module_init(acpi_ec_hc_init);
-module_exit(acpi_ec_hc_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Ducrot Bruno");
-MODULE_DESCRIPTION("ACPI EC SMBus driver");
diff --git a/drivers/acpi/i2c_ec.h b/drivers/acpi/i2c_ec.h
deleted file mode 100644 (file)
index 7c53fb7..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SMBus driver for ACPI Embedded Controller ($Revision: 1.2 $)
- *
- * Copyright (c) 2002, 2005 Ducrot Bruno
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2.
- */
-
-struct acpi_ec_smbus {
-       struct i2c_adapter adapter;
-       union acpi_ec *ec;
-       int base;
-       int alert;
-};
-
-struct acpi_ec_hc {
-       acpi_handle handle;
-       struct acpi_ec_smbus *smbus;
-};
-
-struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device);
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
deleted file mode 100644 (file)
index dc10966..0000000
+++ /dev/null
@@ -1,2798 +0,0 @@
-/*
- *  ibm_acpi.c - IBM ThinkPad ACPI Extras
- *
- *
- *  Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net>
- *  Copyright (C) 2006 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#define IBM_VERSION "0.13"
-
-/*
- *  Changelog:
- *
- *  2006-11-22 0.13    new maintainer
- *                     changelog now lives in git commit history, and will
- *                     not be updated further in-file.
- *  
- *  2005-08-17  0.12   fix compilation on 2.6.13-rc kernels
- *  2005-03-17 0.11    support for 600e, 770x
- *                         thanks to Jamie Lentin <lentinj@dial.pipex.com>
- *                     support for 770e, G41
- *                     G40 and G41 don't have a thinklight
- *                     temperatures no longer experimental
- *                     experimental brightness control
- *                     experimental volume control
- *                     experimental fan enable/disable
- *  2005-01-16 0.10    fix module loading on R30, R31 
- *  2005-01-16 0.9     support for 570, R30, R31
- *                     ultrabay support on A22p, A3x
- *                     limit arg for cmos, led, beep, drop experimental status
- *                     more capable led control on A21e, A22p, T20-22, X20
- *                     experimental temperatures and fan speed
- *                     experimental embedded controller register dump
- *                     mark more functions as __init, drop incorrect __exit
- *                     use MODULE_VERSION
- *                         thanks to Henrik Brix Andersen <brix@gentoo.org>
- *                     fix parameter passing on module loading
- *                         thanks to Rusty Russell <rusty@rustcorp.com.au>
- *                         thanks to Jim Radford <radford@blackbean.org>
- *  2004-11-08 0.8     fix init error case, don't return from a macro
- *                         thanks to Chris Wright <chrisw@osdl.org>
- *  2004-10-23 0.7     fix module loading on A21e, A22p, T20, T21, X20
- *                     fix led control on A21e
- *  2004-10-19 0.6     use acpi_bus_register_driver() to claim HKEY device
- *  2004-10-18 0.5     thinklight support on A21e, G40, R32, T20, T21, X20
- *                     proc file format changed
- *                     video_switch command
- *                     experimental cmos control
- *                     experimental led control
- *                     experimental acpi sounds
- *  2004-09-16 0.4     support for module parameters
- *                     hotkey mask can be prefixed by 0x
- *                     video output switching
- *                     video expansion control
- *                     ultrabay eject support
- *                     removed lcd brightness/on/off control, didn't work
- *  2004-08-17 0.3     support for R40
- *                     lcd off, brightness control
- *                     thinklight on/off
- *  2004-08-14 0.2     support for T series, X20
- *                     bluetooth enable/disable
- *                     hotkey events disabled by default
- *                     removed fan control, currently useless
- *  2004-08-09 0.1     initial release, support for X series
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/string.h>
-
-#include <linux/proc_fs.h>
-#include <linux/backlight.h>
-#include <linux/fb.h>
-#include <asm/uaccess.h>
-
-#include <linux/dmi.h>
-#include <linux/jiffies.h>
-#include <linux/workqueue.h>
-
-#include <acpi/acpi_drivers.h>
-#include <acpi/acnamesp.h>
-
-#define IBM_NAME "ibm"
-#define IBM_DESC "IBM ThinkPad ACPI Extras"
-#define IBM_FILE "ibm_acpi"
-#define IBM_URL "http://ibm-acpi.sf.net/"
-
-MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
-MODULE_DESCRIPTION(IBM_DESC);
-MODULE_VERSION(IBM_VERSION);
-MODULE_LICENSE("GPL");
-
-#define IBM_DIR IBM_NAME
-
-#define IBM_LOG IBM_FILE ": "
-#define IBM_ERR           KERN_ERR    IBM_LOG
-#define IBM_NOTICE KERN_NOTICE IBM_LOG
-#define IBM_INFO   KERN_INFO   IBM_LOG
-#define IBM_DEBUG  KERN_DEBUG  IBM_LOG
-
-#define IBM_MAX_ACPI_ARGS 3
-
-#define __unused __attribute__ ((unused))
-
-static int experimental;
-module_param(experimental, int, 0);
-
-static acpi_handle root_handle = NULL;
-
-#define IBM_HANDLE(object, parent, paths...)                   \
-       static acpi_handle  object##_handle;                    \
-       static acpi_handle *object##_parent = &parent##_handle; \
-       static char        *object##_path;                      \
-       static char        *object##_paths[] = { paths }
-
-IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0",     /* 240, 240x */
-          "\\_SB.PCI.ISA.EC",  /* 570 */
-          "\\_SB.PCI0.ISA0.EC0",       /* 600e/x, 770e, 770x */
-          "\\_SB.PCI0.ISA.EC", /* A21e, A2xm/p, T20-22, X20-21 */
-          "\\_SB.PCI0.AD4S.EC0",       /* i1400, R30 */
-          "\\_SB.PCI0.ICH3.EC0",       /* R31 */
-          "\\_SB.PCI0.LPC.EC", /* all others */
-    );
-
-IBM_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA",     /* 570 */
-          "\\_SB.PCI0.AGP0.VID0",      /* 600e/x, 770x */
-          "\\_SB.PCI0.VID0",   /* 770e */
-          "\\_SB.PCI0.VID",    /* A21e, G4x, R50e, X30, X40 */
-          "\\_SB.PCI0.AGP.VID",        /* all others */
-    );                         /* R30, R31 */
-
-IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */
-
-IBM_HANDLE(cmos, root, "\\UCMS",       /* R50, R50e, R50p, R51, T4x, X31, X40 */
-          "\\CMOS",            /* A3x, G4x, R32, T23, T30, X22-24, X30 */
-          "\\CMS",             /* R40, R40e */
-    );                         /* all others */
-#ifdef CONFIG_ACPI_IBM_DOCK
-IBM_HANDLE(dock, root, "\\_SB.GDCK",   /* X30, X31, X40 */
-          "\\_SB.PCI0.DOCK",   /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
-          "\\_SB.PCI0.PCI1.DOCK",      /* all others */
-          "\\_SB.PCI.ISA.SLCE",        /* 570 */
-    );                         /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
-#endif
-#ifdef CONFIG_ACPI_IBM_BAY
-IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST",       /* 570 */
-          "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
-          "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */ 
-          "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */
-    );                         /* A21e, R30, R31 */
-
-IBM_HANDLE(bay_ej, bay, "_EJ3",        /* 600e/x, A2xm/p, A3x */
-          "_EJ0",              /* all others */
-    );                         /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */
-
-IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV",    /* A3x, R32 */
-          "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */
-    );                         /* all others */
-
-IBM_HANDLE(bay2_ej, bay2, "_EJ3",      /* 600e/x, 770e, A3x */
-          "_EJ0",              /* 770x */
-    );                         /* all others */
-#endif /* CONFIG_ACPI_IBM_BAY */
-
-/* don't list other alternatives as we install a notify handler on the 570 */
-IBM_HANDLE(pci, root, "\\_SB.PCI");    /* 570 */
-
-IBM_HANDLE(hkey, ec, "\\_SB.HKEY",     /* 600e/x, 770e, 770x */
-          "^HKEY",             /* R30, R31 */
-          "HKEY",              /* all others */
-    );                         /* 570 */
-
-IBM_HANDLE(lght, root, "\\LGHT");      /* A21e, A2xm/p, T20-22, X20-21 */
-IBM_HANDLE(ledb, ec, "LEDB");  /* G4x */
-
-IBM_HANDLE(led, ec, "SLED",    /* 570 */
-          "SYSL",              /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
-          "LED",               /* all others */
-    );                         /* R30, R31 */
-
-IBM_HANDLE(beep, ec, "BEEP");  /* all except R30, R31 */
-IBM_HANDLE(ecrd, ec, "ECRD");  /* 570 */
-IBM_HANDLE(ecwr, ec, "ECWR");  /* 570 */
-IBM_HANDLE(fans, ec, "FANS");  /* X31, X40, X41 */
-
-IBM_HANDLE(gfan, ec, "GFAN",   /* 570 */
-          "\\FSPD",            /* 600e/x, 770e, 770x */
-    );                         /* all others */
-
-IBM_HANDLE(sfan, ec, "SFAN",   /* 570 */
-          "JFNS",              /* 770x-JL */
-    );                         /* all others */
-
-#define IBM_HKEY_HID   "IBM0068"
-#define IBM_PCI_HID    "PNP0A03"
-
-enum thermal_access_mode {
-       IBMACPI_THERMAL_NONE = 0,       /* No thermal support */
-       IBMACPI_THERMAL_ACPI_TMP07,     /* Use ACPI TMP0-7 */
-       IBMACPI_THERMAL_ACPI_UPDT,      /* Use ACPI TMP0-7 with UPDT */
-       IBMACPI_THERMAL_TPEC_8,         /* Use ACPI EC regs, 8 sensors */
-       IBMACPI_THERMAL_TPEC_16,        /* Use ACPI EC regs, 16 sensors */
-};
-
-#define IBMACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */
-struct ibm_thermal_sensors_struct {
-       s32 temp[IBMACPI_MAX_THERMAL_SENSORS];
-};
-
-/*
- * FAN ACCESS MODES
- *
- * IBMACPI_FAN_RD_ACPI_GFAN:
- *     ACPI GFAN method: returns fan level
- *
- *     see IBMACPI_FAN_WR_ACPI_SFAN
- *     EC 0x2f not available if GFAN exists
- *
- * IBMACPI_FAN_WR_ACPI_SFAN:
- *     ACPI SFAN method: sets fan level, 0 (stop) to 7 (max)
- *
- *     EC 0x2f might be available *for reading*, but never for writing.
- *
- * IBMACPI_FAN_WR_TPEC:
- *     ThinkPad EC register 0x2f (HFSP): fan control loop mode Supported
- *     on almost all ThinkPads
- *
- *     Fan speed changes of any sort (including those caused by the
- *     disengaged mode) are usually done slowly by the firmware as the
- *     maximum ammount of fan duty cycle change per second seems to be
- *     limited.
- *
- *     Reading is not available if GFAN exists.
- *     Writing is not available if SFAN exists.
- *
- *     Bits
- *      7      automatic mode engaged;
- *             (default operation mode of the ThinkPad)
- *             fan level is ignored in this mode.
- *      6      disengage mode (takes precedence over bit 7);
- *             not available on all thinkpads.  May disable
- *             the tachometer, and speeds up fan to 100% duty-cycle,
- *             which speeds it up far above the standard RPM
- *             levels.  It is not impossible that it could cause
- *             hardware damage.
- *     5-3     unused in some models.  Extra bits for fan level
- *             in others, but still useless as all values above
- *             7 map to the same speed as level 7 in these models.
- *     2-0     fan level (0..7 usually)
- *                     0x00 = stop
- *                     0x07 = max (set when temperatures critical)
- *             Some ThinkPads may have other levels, see
- *             IBMACPI_FAN_WR_ACPI_FANS (X31/X40/X41)
- *
- *     FIRMWARE BUG: on some models, EC 0x2f might not be initialized at
- *     boot. Apparently the EC does not intialize it, so unless ACPI DSDT
- *     does so, its initial value is meaningless (0x07).
- *
- *     For firmware bugs, refer to:
- *     http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
- *
- *     ----
- *
- *     ThinkPad EC register 0x84 (LSB), 0x85 (MSB):
- *     Main fan tachometer reading (in RPM)
- *
- *     This register is present on all ThinkPads with a new-style EC, and
- *     it is known not to be present on the A21m/e, and T22, as there is
- *     something else in offset 0x84 according to the ACPI DSDT.  Other
- *     ThinkPads from this same time period (and earlier) probably lack the
- *     tachometer as well.
- *
- *     Unfortunately a lot of ThinkPads with new-style ECs but whose firwmare
- *     was never fixed by IBM to report the EC firmware version string
- *     probably support the tachometer (like the early X models), so
- *     detecting it is quite hard.  We need more data to know for sure.
- *
- *     FIRMWARE BUG: always read 0x84 first, otherwise incorrect readings
- *     might result.
- *
- *     FIRMWARE BUG: when EC 0x2f bit 6 is set (disengaged mode), this
- *     register is not invalidated in ThinkPads that disable tachometer
- *     readings.  Thus, the tachometer readings go stale.
- *
- *     For firmware bugs, refer to:
- *     http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
- *
- * IBMACPI_FAN_WR_ACPI_FANS:
- *     ThinkPad X31, X40, X41.  Not available in the X60.
- *
- *     FANS ACPI handle: takes three arguments: low speed, medium speed,
- *     high speed.  ACPI DSDT seems to map these three speeds to levels
- *     as follows: STOP LOW LOW MED MED HIGH HIGH HIGH HIGH
- *     (this map is stored on FAN0..FAN8 as "0,1,1,2,2,3,3,3,3")
- *
- *     The speeds are stored on handles
- *     (FANA:FAN9), (FANC:FANB), (FANE:FAND).
- *
- *     There are three default speed sets, acessible as handles:
- *     FS1L,FS1M,FS1H; FS2L,FS2M,FS2H; FS3L,FS3M,FS3H
- *
- *     ACPI DSDT switches which set is in use depending on various
- *     factors.
- *
- *     IBMACPI_FAN_WR_TPEC is also available and should be used to
- *     command the fan.  The X31/X40/X41 seems to have 8 fan levels,
- *     but the ACPI tables just mention level 7.
- */
-
-enum fan_status_access_mode {
-       IBMACPI_FAN_NONE = 0,           /* No fan status or control */
-       IBMACPI_FAN_RD_ACPI_GFAN,       /* Use ACPI GFAN */
-       IBMACPI_FAN_RD_TPEC,            /* Use ACPI EC regs 0x2f, 0x84-0x85 */
-};
-
-enum fan_control_access_mode {
-       IBMACPI_FAN_WR_NONE = 0,        /* No fan control */
-       IBMACPI_FAN_WR_ACPI_SFAN,       /* Use ACPI SFAN */
-       IBMACPI_FAN_WR_TPEC,            /* Use ACPI EC reg 0x2f */
-       IBMACPI_FAN_WR_ACPI_FANS,       /* Use ACPI FANS and EC reg 0x2f */
-};
-
-enum fan_control_commands {
-       IBMACPI_FAN_CMD_SPEED   = 0x0001,       /* speed command */
-       IBMACPI_FAN_CMD_LEVEL   = 0x0002,       /* level command  */
-       IBMACPI_FAN_CMD_ENABLE  = 0x0004,       /* enable/disable cmd,
-                                                * and also watchdog cmd */
-};
-
-enum {                                 /* Fan control constants */
-       fan_status_offset = 0x2f,       /* EC register 0x2f */
-       fan_rpm_offset = 0x84,          /* EC register 0x84: LSB, 0x85 MSB (RPM)
-                                        * 0x84 must be read before 0x85 */
-
-       IBMACPI_FAN_EC_DISENGAGED       = 0x40, /* EC mode: tachometer
-                                                * disengaged */
-       IBMACPI_FAN_EC_AUTO             = 0x80, /* EC mode: auto fan
-                                                * control */
-};
-
-static char *ibm_thinkpad_ec_found = NULL;
-
-struct ibm_struct {
-       char *name;
-       char param[32];
-
-       char *hid;
-       struct acpi_driver *driver;
-
-       int (*init) (void);
-       int (*read) (char *);
-       int (*write) (char *);
-       void (*exit) (void);
-
-       void (*notify) (struct ibm_struct *, u32);
-       acpi_handle *handle;
-       int type;
-       struct acpi_device *device;
-
-       int driver_registered;
-       int proc_created;
-       int init_called;
-       int notify_installed;
-
-       int experimental;
-};
-
-static struct proc_dir_entry *proc_dir = NULL;
-
-static struct backlight_device *ibm_backlight_device = NULL;
-
-#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
-#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
-#define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
-
-static int acpi_evalf(acpi_handle handle,
-                     void *res, char *method, char *fmt, ...)
-{
-       char *fmt0 = fmt;
-       struct acpi_object_list params;
-       union acpi_object in_objs[IBM_MAX_ACPI_ARGS];
-       struct acpi_buffer result, *resultp;
-       union acpi_object out_obj;
-       acpi_status status;
-       va_list ap;
-       char res_type;
-       int success;
-       int quiet;
-
-       if (!*fmt) {
-               printk(IBM_ERR "acpi_evalf() called with empty format\n");
-               return 0;
-       }
-
-       if (*fmt == 'q') {
-               quiet = 1;
-               fmt++;
-       } else
-               quiet = 0;
-
-       res_type = *(fmt++);
-
-       params.count = 0;
-       params.pointer = &in_objs[0];
-
-       va_start(ap, fmt);
-       while (*fmt) {
-               char c = *(fmt++);
-               switch (c) {
-               case 'd':       /* int */
-                       in_objs[params.count].integer.value = va_arg(ap, int);
-                       in_objs[params.count++].type = ACPI_TYPE_INTEGER;
-                       break;
-                       /* add more types as needed */
-               default:
-                       printk(IBM_ERR "acpi_evalf() called "
-                              "with invalid format character '%c'\n", c);
-                       return 0;
-               }
-       }
-       va_end(ap);
-
-       if (res_type != 'v') {
-               result.length = sizeof(out_obj);
-               result.pointer = &out_obj;
-               resultp = &result;
-       } else
-               resultp = NULL;
-
-       status = acpi_evaluate_object(handle, method, &params, resultp);
-
-       switch (res_type) {
-       case 'd':               /* int */
-               if (res)
-                       *(int *)res = out_obj.integer.value;
-               success = status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER;
-               break;
-       case 'v':               /* void */
-               success = status == AE_OK;
-               break;
-               /* add more types as needed */
-       default:
-               printk(IBM_ERR "acpi_evalf() called "
-                      "with invalid format character '%c'\n", res_type);
-               return 0;
-       }
-
-       if (!success && !quiet)
-               printk(IBM_ERR "acpi_evalf(%s, %s, ...) failed: %d\n",
-                      method, fmt0, status);
-
-       return success;
-}
-
-static void __unused acpi_print_int(acpi_handle handle, char *method)
-{
-       int i;
-
-       if (acpi_evalf(handle, &i, method, "d"))
-               printk(IBM_INFO "%s = 0x%x\n", method, i);
-       else
-               printk(IBM_ERR "error calling %s\n", method);
-}
-
-static char *next_cmd(char **cmds)
-{
-       char *start = *cmds;
-       char *end;
-
-       while ((end = strchr(start, ',')) && end == start)
-               start = end + 1;
-
-       if (!end)
-               return NULL;
-
-       *end = 0;
-       *cmds = end + 1;
-       return start;
-}
-
-static int ibm_acpi_driver_init(void)
-{
-       printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
-       printk(IBM_INFO "%s\n", IBM_URL);
-
-       if (ibm_thinkpad_ec_found)
-               printk(IBM_INFO "ThinkPad EC firmware %s\n",
-                      ibm_thinkpad_ec_found);
-
-       return 0;
-}
-
-static int driver_read(char *p)
-{
-       int len = 0;
-
-       len += sprintf(p + len, "driver:\t\t%s\n", IBM_DESC);
-       len += sprintf(p + len, "version:\t%s\n", IBM_VERSION);
-
-       return len;
-}
-
-static int hotkey_supported;
-static int hotkey_mask_supported;
-static int hotkey_orig_status;
-static int hotkey_orig_mask;
-
-static int hotkey_get(int *status, int *mask)
-{
-       if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
-               return 0;
-
-       if (hotkey_mask_supported)
-               if (!acpi_evalf(hkey_handle, mask, "DHKN", "d"))
-                       return 0;
-
-       return 1;
-}
-
-static int hotkey_set(int status, int mask)
-{
-       int i;
-
-       if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
-               return 0;
-
-       if (hotkey_mask_supported)
-               for (i = 0; i < 32; i++) {
-                       int bit = ((1 << i) & mask) != 0;
-                       if (!acpi_evalf(hkey_handle,
-                                       NULL, "MHKM", "vdd", i + 1, bit))
-                               return 0;
-               }
-
-       return 1;
-}
-
-static int hotkey_init(void)
-{
-       /* hotkey not supported on 570 */
-       hotkey_supported = hkey_handle != NULL;
-
-       if (hotkey_supported) {
-               /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
-                  A30, R30, R31, T20-22, X20-21, X22-24 */
-               hotkey_mask_supported =
-                   acpi_evalf(hkey_handle, NULL, "DHKN", "qv");
-
-               if (!hotkey_get(&hotkey_orig_status, &hotkey_orig_mask))
-                       return -ENODEV;
-       }
-
-       return 0;
-}
-
-static int hotkey_read(char *p)
-{
-       int status, mask;
-       int len = 0;
-
-       if (!hotkey_supported) {
-               len += sprintf(p + len, "status:\t\tnot supported\n");
-               return len;
-       }
-
-       if (!hotkey_get(&status, &mask))
-               return -EIO;
-
-       len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
-       if (hotkey_mask_supported) {
-               len += sprintf(p + len, "mask:\t\t0x%04x\n", mask);
-               len += sprintf(p + len,
-                              "commands:\tenable, disable, reset, <mask>\n");
-       } else {
-               len += sprintf(p + len, "mask:\t\tnot supported\n");
-               len += sprintf(p + len, "commands:\tenable, disable, reset\n");
-       }
-
-       return len;
-}
-
-static int hotkey_write(char *buf)
-{
-       int status, mask;
-       char *cmd;
-       int do_cmd = 0;
-
-       if (!hotkey_supported)
-               return -ENODEV;
-
-       if (!hotkey_get(&status, &mask))
-               return -EIO;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (strlencmp(cmd, "enable") == 0) {
-                       status = 1;
-               } else if (strlencmp(cmd, "disable") == 0) {
-                       status = 0;
-               } else if (strlencmp(cmd, "reset") == 0) {
-                       status = hotkey_orig_status;
-                       mask = hotkey_orig_mask;
-               } else if (sscanf(cmd, "0x%x", &mask) == 1) {
-                       /* mask set */
-               } else if (sscanf(cmd, "%x", &mask) == 1) {
-                       /* mask set */
-               } else
-                       return -EINVAL;
-               do_cmd = 1;
-       }
-
-       if (do_cmd && !hotkey_set(status, mask))
-               return -EIO;
-
-       return 0;
-}
-
-static void hotkey_exit(void)
-{
-       if (hotkey_supported)
-               hotkey_set(hotkey_orig_status, hotkey_orig_mask);
-}
-
-static void hotkey_notify(struct ibm_struct *ibm, u32 event)
-{
-       int hkey;
-
-       if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d"))
-               acpi_bus_generate_event(ibm->device, event, hkey);
-       else {
-               printk(IBM_ERR "unknown hotkey event %d\n", event);
-               acpi_bus_generate_event(ibm->device, event, 0);
-       }
-}
-
-static int bluetooth_supported;
-
-static int bluetooth_init(void)
-{
-       /* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
-          G4x, R30, R31, R40e, R50e, T20-22, X20-21 */
-       bluetooth_supported = hkey_handle &&
-           acpi_evalf(hkey_handle, NULL, "GBDC", "qv");
-
-       return 0;
-}
-
-static int bluetooth_status(void)
-{
-       int status;
-
-       if (!bluetooth_supported ||
-           !acpi_evalf(hkey_handle, &status, "GBDC", "d"))
-               status = 0;
-
-       return status;
-}
-
-static int bluetooth_read(char *p)
-{
-       int len = 0;
-       int status = bluetooth_status();
-
-       if (!bluetooth_supported)
-               len += sprintf(p + len, "status:\t\tnot supported\n");
-       else if (!(status & 1))
-               len += sprintf(p + len, "status:\t\tnot installed\n");
-       else {
-               len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 1));
-               len += sprintf(p + len, "commands:\tenable, disable\n");
-       }
-
-       return len;
-}
-
-static int bluetooth_write(char *buf)
-{
-       int status = bluetooth_status();
-       char *cmd;
-       int do_cmd = 0;
-
-       if (!bluetooth_supported)
-               return -ENODEV;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (strlencmp(cmd, "enable") == 0) {
-                       status |= 2;
-               } else if (strlencmp(cmd, "disable") == 0) {
-                       status &= ~2;
-               } else
-                       return -EINVAL;
-               do_cmd = 1;
-       }
-
-       if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
-               return -EIO;
-
-       return 0;
-}
-
-static int wan_supported;
-
-static int wan_init(void)
-{
-       wan_supported = hkey_handle &&
-           acpi_evalf(hkey_handle, NULL, "GWAN", "qv");
-
-       return 0;
-}
-
-static int wan_status(void)
-{
-       int status;
-
-       if (!wan_supported || !acpi_evalf(hkey_handle, &status, "GWAN", "d"))
-               status = 0;
-
-       return status;
-}
-
-static int wan_read(char *p)
-{
-       int len = 0;
-       int status = wan_status();
-
-       if (!wan_supported)
-               len += sprintf(p + len, "status:\t\tnot supported\n");
-       else if (!(status & 1))
-               len += sprintf(p + len, "status:\t\tnot installed\n");
-       else {
-               len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 1));
-               len += sprintf(p + len, "commands:\tenable, disable\n");
-       }
-
-       return len;
-}
-
-static int wan_write(char *buf)
-{
-       int status = wan_status();
-       char *cmd;
-       int do_cmd = 0;
-
-       if (!wan_supported)
-               return -ENODEV;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (strlencmp(cmd, "enable") == 0) {
-                       status |= 2;
-               } else if (strlencmp(cmd, "disable") == 0) {
-                       status &= ~2;
-               } else
-                       return -EINVAL;
-               do_cmd = 1;
-       }
-
-       if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
-               return -EIO;
-
-       return 0;
-}
-
-enum video_access_mode {
-       IBMACPI_VIDEO_NONE = 0,
-       IBMACPI_VIDEO_570,      /* 570 */
-       IBMACPI_VIDEO_770,      /* 600e/x, 770e, 770x */
-       IBMACPI_VIDEO_NEW,      /* all others */
-};
-
-static enum video_access_mode video_supported;
-static int video_orig_autosw;
-
-static int video_init(void)
-{
-       int ivga;
-
-       if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga)
-               /* G41, assume IVGA doesn't change */
-               vid_handle = vid2_handle;
-
-       if (!vid_handle)
-               /* video switching not supported on R30, R31 */
-               video_supported = IBMACPI_VIDEO_NONE;
-       else if (acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd"))
-               /* 570 */
-               video_supported = IBMACPI_VIDEO_570;
-       else if (acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd"))
-               /* 600e/x, 770e, 770x */
-               video_supported = IBMACPI_VIDEO_770;
-       else
-               /* all others */
-               video_supported = IBMACPI_VIDEO_NEW;
-
-       return 0;
-}
-
-static int video_status(void)
-{
-       int status = 0;
-       int i;
-
-       if (video_supported == IBMACPI_VIDEO_570) {
-               if (acpi_evalf(NULL, &i, "\\_SB.PHS", "dd", 0x87))
-                       status = i & 3;
-       } else if (video_supported == IBMACPI_VIDEO_770) {
-               if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
-                       status |= 0x01 * i;
-               if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
-                       status |= 0x02 * i;
-       } else if (video_supported == IBMACPI_VIDEO_NEW) {
-               acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1);
-               if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
-                       status |= 0x02 * i;
-
-               acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0);
-               if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
-                       status |= 0x01 * i;
-               if (acpi_evalf(NULL, &i, "\\VCDD", "d"))
-                       status |= 0x08 * i;
-       }
-
-       return status;
-}
-
-static int video_autosw(void)
-{
-       int autosw = 0;
-
-       if (video_supported == IBMACPI_VIDEO_570)
-               acpi_evalf(vid_handle, &autosw, "SWIT", "d");
-       else if (video_supported == IBMACPI_VIDEO_770 ||
-                video_supported == IBMACPI_VIDEO_NEW)
-               acpi_evalf(vid_handle, &autosw, "^VDEE", "d");
-
-       return autosw & 1;
-}
-
-static int video_read(char *p)
-{
-       int status = video_status();
-       int autosw = video_autosw();
-       int len = 0;
-
-       if (!video_supported) {
-               len += sprintf(p + len, "status:\t\tnot supported\n");
-               return len;
-       }
-
-       len += sprintf(p + len, "status:\t\tsupported\n");
-       len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
-       len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
-       if (video_supported == IBMACPI_VIDEO_NEW)
-               len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
-       len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
-       len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
-       len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
-       if (video_supported == IBMACPI_VIDEO_NEW)
-               len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
-       len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
-       len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
-
-       return len;
-}
-
-static int video_switch(void)
-{
-       int autosw = video_autosw();
-       int ret;
-
-       if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
-               return -EIO;
-       ret = video_supported == IBMACPI_VIDEO_570 ?
-           acpi_evalf(ec_handle, NULL, "_Q16", "v") :
-           acpi_evalf(vid_handle, NULL, "VSWT", "v");
-       acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw);
-
-       return ret;
-}
-
-static int video_expand(void)
-{
-       if (video_supported == IBMACPI_VIDEO_570)
-               return acpi_evalf(ec_handle, NULL, "_Q17", "v");
-       else if (video_supported == IBMACPI_VIDEO_770)
-               return acpi_evalf(vid_handle, NULL, "VEXP", "v");
-       else
-               return acpi_evalf(NULL, NULL, "\\VEXP", "v");
-}
-
-static int video_switch2(int status)
-{
-       int ret;
-
-       if (video_supported == IBMACPI_VIDEO_570) {
-               ret = acpi_evalf(NULL, NULL,
-                                "\\_SB.PHS2", "vdd", 0x8b, status | 0x80);
-       } else if (video_supported == IBMACPI_VIDEO_770) {
-               int autosw = video_autosw();
-               if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
-                       return -EIO;
-
-               ret = acpi_evalf(vid_handle, NULL,
-                                "ASWT", "vdd", status * 0x100, 0);
-
-               acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw);
-       } else {
-               ret = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) &&
-                   acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
-       }
-
-       return ret;
-}
-
-static int video_write(char *buf)
-{
-       char *cmd;
-       int enable, disable, status;
-
-       if (!video_supported)
-               return -ENODEV;
-
-       enable = disable = 0;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (strlencmp(cmd, "lcd_enable") == 0) {
-                       enable |= 0x01;
-               } else if (strlencmp(cmd, "lcd_disable") == 0) {
-                       disable |= 0x01;
-               } else if (strlencmp(cmd, "crt_enable") == 0) {
-                       enable |= 0x02;
-               } else if (strlencmp(cmd, "crt_disable") == 0) {
-                       disable |= 0x02;
-               } else if (video_supported == IBMACPI_VIDEO_NEW &&
-                          strlencmp(cmd, "dvi_enable") == 0) {
-                       enable |= 0x08;
-               } else if (video_supported == IBMACPI_VIDEO_NEW &&
-                          strlencmp(cmd, "dvi_disable") == 0) {
-                       disable |= 0x08;
-               } else if (strlencmp(cmd, "auto_enable") == 0) {
-                       if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
-                               return -EIO;
-               } else if (strlencmp(cmd, "auto_disable") == 0) {
-                       if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 0))
-                               return -EIO;
-               } else if (strlencmp(cmd, "video_switch") == 0) {
-                       if (!video_switch())
-                               return -EIO;
-               } else if (strlencmp(cmd, "expand_toggle") == 0) {
-                       if (!video_expand())
-                               return -EIO;
-               } else
-                       return -EINVAL;
-       }
-
-       if (enable || disable) {
-               status = (video_status() & 0x0f & ~disable) | enable;
-               if (!video_switch2(status))
-                       return -EIO;
-       }
-
-       return 0;
-}
-
-static void video_exit(void)
-{
-       acpi_evalf(vid_handle, NULL, "_DOS", "vd", video_orig_autosw);
-}
-
-static int light_supported;
-static int light_status_supported;
-
-static int light_init(void)
-{
-       /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */
-       light_supported = (cmos_handle || lght_handle) && !ledb_handle;
-
-       if (light_supported)
-               /* light status not supported on
-                  570, 600e/x, 770e, 770x, G4x, R30, R31, R32, X20 */
-               light_status_supported = acpi_evalf(ec_handle, NULL,
-                                                   "KBLT", "qv");
-
-       return 0;
-}
-
-static int light_read(char *p)
-{
-       int len = 0;
-       int status = 0;
-
-       if (!light_supported) {
-               len += sprintf(p + len, "status:\t\tnot supported\n");
-       } else if (!light_status_supported) {
-               len += sprintf(p + len, "status:\t\tunknown\n");
-               len += sprintf(p + len, "commands:\ton, off\n");
-       } else {
-               if (!acpi_evalf(ec_handle, &status, "KBLT", "d"))
-                       return -EIO;
-               len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
-               len += sprintf(p + len, "commands:\ton, off\n");
-       }
-
-       return len;
-}
-
-static int light_write(char *buf)
-{
-       int cmos_cmd, lght_cmd;
-       char *cmd;
-       int success;
-
-       if (!light_supported)
-               return -ENODEV;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (strlencmp(cmd, "on") == 0) {
-                       cmos_cmd = 0x0c;
-                       lght_cmd = 1;
-               } else if (strlencmp(cmd, "off") == 0) {
-                       cmos_cmd = 0x0d;
-                       lght_cmd = 0;
-               } else
-                       return -EINVAL;
-
-               success = cmos_handle ?
-                   acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) :
-                   acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd);
-               if (!success)
-                       return -EIO;
-       }
-
-       return 0;
-}
-
-#if defined(CONFIG_ACPI_IBM_DOCK) || defined(CONFIG_ACPI_IBM_BAY)
-static int _sta(acpi_handle handle)
-{
-       int status;
-
-       if (!handle || !acpi_evalf(handle, &status, "_STA", "d"))
-               status = 0;
-
-       return status;
-}
-#endif
-
-#ifdef CONFIG_ACPI_IBM_DOCK
-#define dock_docked() (_sta(dock_handle) & 1)
-
-static int dock_read(char *p)
-{
-       int len = 0;
-       int docked = dock_docked();
-
-       if (!dock_handle)
-               len += sprintf(p + len, "status:\t\tnot supported\n");
-       else if (!docked)
-               len += sprintf(p + len, "status:\t\tundocked\n");
-       else {
-               len += sprintf(p + len, "status:\t\tdocked\n");
-               len += sprintf(p + len, "commands:\tdock, undock\n");
-       }
-
-       return len;
-}
-
-static int dock_write(char *buf)
-{
-       char *cmd;
-
-       if (!dock_docked())
-               return -ENODEV;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (strlencmp(cmd, "undock") == 0) {
-                       if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) ||
-                           !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
-                               return -EIO;
-               } else if (strlencmp(cmd, "dock") == 0) {
-                       if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1))
-                               return -EIO;
-               } else
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void dock_notify(struct ibm_struct *ibm, u32 event)
-{
-       int docked = dock_docked();
-       int pci = ibm->hid && strstr(ibm->hid, IBM_PCI_HID);
-
-       if (event == 1 && !pci) /* 570 */
-               acpi_bus_generate_event(ibm->device, event, 1); /* button */
-       else if (event == 1 && pci)     /* 570 */
-               acpi_bus_generate_event(ibm->device, event, 3); /* dock */
-       else if (event == 3 && docked)
-               acpi_bus_generate_event(ibm->device, event, 1); /* button */
-       else if (event == 3 && !docked)
-               acpi_bus_generate_event(ibm->device, event, 2); /* undock */
-       else if (event == 0 && docked)
-               acpi_bus_generate_event(ibm->device, event, 3); /* dock */
-       else {
-               printk(IBM_ERR "unknown dock event %d, status %d\n",
-                      event, _sta(dock_handle));
-               acpi_bus_generate_event(ibm->device, event, 0); /* unknown */
-       }
-}
-#endif
-
-#ifdef CONFIG_ACPI_IBM_BAY
-static int bay_status_supported;
-static int bay_status2_supported;
-static int bay_eject_supported;
-static int bay_eject2_supported;
-
-static int bay_init(void)
-{
-       bay_status_supported = bay_handle &&
-           acpi_evalf(bay_handle, NULL, "_STA", "qv");
-       bay_status2_supported = bay2_handle &&
-           acpi_evalf(bay2_handle, NULL, "_STA", "qv");
-
-       bay_eject_supported = bay_handle && bay_ej_handle &&
-           (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental);
-       bay_eject2_supported = bay2_handle && bay2_ej_handle &&
-           (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental);
-
-       return 0;
-}
-
-#define bay_occupied(b) (_sta(b##_handle) & 1)
-
-static int bay_read(char *p)
-{
-       int len = 0;
-       int occupied = bay_occupied(bay);
-       int occupied2 = bay_occupied(bay2);
-       int eject, eject2;
-
-       len += sprintf(p + len, "status:\t\t%s\n", bay_status_supported ?
-                      (occupied ? "occupied" : "unoccupied") :
-                      "not supported");
-       if (bay_status2_supported)
-               len += sprintf(p + len, "status2:\t%s\n", occupied2 ?
-                              "occupied" : "unoccupied");
-
-       eject = bay_eject_supported && occupied;
-       eject2 = bay_eject2_supported && occupied2;
-
-       if (eject && eject2)
-               len += sprintf(p + len, "commands:\teject, eject2\n");
-       else if (eject)
-               len += sprintf(p + len, "commands:\teject\n");
-       else if (eject2)
-               len += sprintf(p + len, "commands:\teject2\n");
-
-       return len;
-}
-
-static int bay_write(char *buf)
-{
-       char *cmd;
-
-       if (!bay_eject_supported && !bay_eject2_supported)
-               return -ENODEV;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (bay_eject_supported && strlencmp(cmd, "eject") == 0) {
-                       if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1))
-                               return -EIO;
-               } else if (bay_eject2_supported &&
-                          strlencmp(cmd, "eject2") == 0) {
-                       if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1))
-                               return -EIO;
-               } else
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void bay_notify(struct ibm_struct *ibm, u32 event)
-{
-       acpi_bus_generate_event(ibm->device, event, 0);
-}
-#endif /* CONFIG_ACPI_IBM_BAY */
-
-static int cmos_read(char *p)
-{
-       int len = 0;
-
-       /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
-          R30, R31, T20-22, X20-21 */
-       if (!cmos_handle)
-               len += sprintf(p + len, "status:\t\tnot supported\n");
-       else {
-               len += sprintf(p + len, "status:\t\tsupported\n");
-               len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n");
-       }
-
-       return len;
-}
-
-static int cmos_eval(int cmos_cmd)
-{
-       if (cmos_handle)
-               return acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd);
-       else
-               return 1;
-}
-
-static int cmos_write(char *buf)
-{
-       char *cmd;
-       int cmos_cmd;
-
-       if (!cmos_handle)
-               return -EINVAL;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (sscanf(cmd, "%u", &cmos_cmd) == 1 &&
-                   cmos_cmd >= 0 && cmos_cmd <= 21) {
-                       /* cmos_cmd set */
-               } else
-                       return -EINVAL;
-
-               if (!cmos_eval(cmos_cmd))
-                       return -EIO;
-       }
-
-       return 0;
-}
-
-enum led_access_mode {
-       IBMACPI_LED_NONE = 0,
-       IBMACPI_LED_570,        /* 570 */
-       IBMACPI_LED_OLD,        /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
-       IBMACPI_LED_NEW,        /* all others */
-};
-static enum led_access_mode led_supported;
-
-static int led_init(void)
-{
-       if (!led_handle)
-               /* led not supported on R30, R31 */
-               led_supported = IBMACPI_LED_NONE;
-       else if (strlencmp(led_path, "SLED") == 0)
-               /* 570 */
-               led_supported = IBMACPI_LED_570;
-       else if (strlencmp(led_path, "SYSL") == 0)
-               /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
-               led_supported = IBMACPI_LED_OLD;
-       else
-               /* all others */
-               led_supported = IBMACPI_LED_NEW;
-
-       return 0;
-}
-
-#define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking"))
-
-static int led_read(char *p)
-{
-       int len = 0;
-
-       if (!led_supported) {
-               len += sprintf(p + len, "status:\t\tnot supported\n");
-               return len;
-       }
-       len += sprintf(p + len, "status:\t\tsupported\n");
-
-       if (led_supported == IBMACPI_LED_570) {
-               /* 570 */
-               int i, status;
-               for (i = 0; i < 8; i++) {
-                       if (!acpi_evalf(ec_handle,
-                                       &status, "GLED", "dd", 1 << i))
-                               return -EIO;
-                       len += sprintf(p + len, "%d:\t\t%s\n",
-                                      i, led_status(status));
-               }
-       }
-
-       len += sprintf(p + len, "commands:\t"
-                      "<led> on, <led> off, <led> blink (<led> is 0-7)\n");
-
-       return len;
-}
-
-/* off, on, blink */
-static const int led_sled_arg1[] = { 0, 1, 3 };
-static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */
-static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */
-static const int led_led_arg1[] = { 0, 0x80, 0xc0 };
-
-#define EC_HLCL 0x0c
-#define EC_HLBL 0x0d
-#define EC_HLMS 0x0e
-
-static int led_write(char *buf)
-{
-       char *cmd;
-       int led, ind, ret;
-
-       if (!led_supported)
-               return -ENODEV;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 7)
-                       return -EINVAL;
-
-               if (strstr(cmd, "off")) {
-                       ind = 0;
-               } else if (strstr(cmd, "on")) {
-                       ind = 1;
-               } else if (strstr(cmd, "blink")) {
-                       ind = 2;
-               } else
-                       return -EINVAL;
-
-               if (led_supported == IBMACPI_LED_570) {
-                       /* 570 */
-                       led = 1 << led;
-                       if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
-                                       led, led_sled_arg1[ind]))
-                               return -EIO;
-               } else if (led_supported == IBMACPI_LED_OLD) {
-                       /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
-                       led = 1 << led;
-                       ret = ec_write(EC_HLMS, led);
-                       if (ret >= 0)
-                               ret =
-                                   ec_write(EC_HLBL, led * led_exp_hlbl[ind]);
-                       if (ret >= 0)
-                               ret =
-                                   ec_write(EC_HLCL, led * led_exp_hlcl[ind]);
-                       if (ret < 0)
-                               return ret;
-               } else {
-                       /* all others */
-                       if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
-                                       led, led_led_arg1[ind]))
-                               return -EIO;
-               }
-       }
-
-       return 0;
-}
-
-static int beep_read(char *p)
-{
-       int len = 0;
-
-       if (!beep_handle)
-               len += sprintf(p + len, "status:\t\tnot supported\n");
-       else {
-               len += sprintf(p + len, "status:\t\tsupported\n");
-               len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n");
-       }
-
-       return len;
-}
-
-static int beep_write(char *buf)
-{
-       char *cmd;
-       int beep_cmd;
-
-       if (!beep_handle)
-               return -ENODEV;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (sscanf(cmd, "%u", &beep_cmd) == 1 &&
-                   beep_cmd >= 0 && beep_cmd <= 17) {
-                       /* beep_cmd set */
-               } else
-                       return -EINVAL;
-               if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", beep_cmd, 0))
-                       return -EIO;
-       }
-
-       return 0;
-}
-
-static int acpi_ec_read(int i, u8 * p)
-{
-       int v;
-
-       if (ecrd_handle) {
-               if (!acpi_evalf(ecrd_handle, &v, NULL, "dd", i))
-                       return 0;
-               *p = v;
-       } else {
-               if (ec_read(i, p) < 0)
-                       return 0;
-       }
-
-       return 1;
-}
-
-static int acpi_ec_write(int i, u8 v)
-{
-       if (ecwr_handle) {
-               if (!acpi_evalf(ecwr_handle, NULL, NULL, "vdd", i, v))
-                       return 0;
-       } else {
-               if (ec_write(i, v) < 0)
-                       return 0;
-       }
-
-       return 1;
-}
-
-static enum thermal_access_mode thermal_read_mode;
-
-static int thermal_init(void)
-{
-       u8 t, ta1, ta2;
-       int i;
-       int acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
-
-       if (ibm_thinkpad_ec_found && experimental) {
-               /*
-                * Direct EC access mode: sensors at registers
-                * 0x78-0x7F, 0xC0-0xC7.  Registers return 0x00 for
-                * non-implemented, thermal sensors return 0x80 when
-                * not available
-                */
-
-               ta1 = ta2 = 0;
-               for (i = 0; i < 8; i++) {
-                       if (likely(acpi_ec_read(0x78 + i, &t))) {
-                               ta1 |= t;
-                       } else {
-                               ta1 = 0;
-                               break;
-                       }
-                       if (likely(acpi_ec_read(0xC0 + i, &t))) {
-                               ta2 |= t;
-                       } else {
-                               ta1 = 0;
-                               break;
-                       }
-               }
-               if (ta1 == 0) {
-                       /* This is sheer paranoia, but we handle it anyway */
-                       if (acpi_tmp7) {
-                               printk(IBM_ERR
-                                      "ThinkPad ACPI EC access misbehaving, "
-                                      "falling back to ACPI TMPx access mode\n");
-                               thermal_read_mode = IBMACPI_THERMAL_ACPI_TMP07;
-                       } else {
-                               printk(IBM_ERR
-                                      "ThinkPad ACPI EC access misbehaving, "
-                                      "disabling thermal sensors access\n");
-                               thermal_read_mode = IBMACPI_THERMAL_NONE;
-                       }
-               } else {
-                       thermal_read_mode =
-                           (ta2 != 0) ?
-                           IBMACPI_THERMAL_TPEC_16 : IBMACPI_THERMAL_TPEC_8;
-               }
-       } else if (acpi_tmp7) {
-               if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) {
-                       /* 600e/x, 770e, 770x */
-                       thermal_read_mode = IBMACPI_THERMAL_ACPI_UPDT;
-               } else {
-                       /* Standard ACPI TMPx access, max 8 sensors */
-                       thermal_read_mode = IBMACPI_THERMAL_ACPI_TMP07;
-               }
-       } else {
-               /* temperatures not supported on 570, G4x, R30, R31, R32 */
-               thermal_read_mode = IBMACPI_THERMAL_NONE;
-       }
-
-       return 0;
-}
-
-static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
-{
-       int i, t;
-       s8 tmp;
-       char tmpi[] = "TMPi";
-
-       if (!s)
-               return -EINVAL;
-
-       switch (thermal_read_mode) {
-#if IBMACPI_MAX_THERMAL_SENSORS >= 16
-       case IBMACPI_THERMAL_TPEC_16:
-               for (i = 0; i < 8; i++) {
-                       if (!acpi_ec_read(0xC0 + i, &tmp))
-                               return -EIO;
-                       s->temp[i + 8] = tmp * 1000;
-               }
-               /* fallthrough */
-#endif
-       case IBMACPI_THERMAL_TPEC_8:
-               for (i = 0; i < 8; i++) {
-                       if (!acpi_ec_read(0x78 + i, &tmp))
-                               return -EIO;
-                       s->temp[i] = tmp * 1000;
-               }
-               return (thermal_read_mode == IBMACPI_THERMAL_TPEC_16) ? 16 : 8;
-
-       case IBMACPI_THERMAL_ACPI_UPDT:
-               if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
-                       return -EIO;
-               for (i = 0; i < 8; i++) {
-                       tmpi[3] = '0' + i;
-                       if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
-                               return -EIO;
-                       s->temp[i] = (t - 2732) * 100;
-               }
-               return 8;
-
-       case IBMACPI_THERMAL_ACPI_TMP07:
-               for (i = 0; i < 8; i++) {
-                       tmpi[3] = '0' + i;
-                       if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
-                               return -EIO;
-                       s->temp[i] = t * 1000;
-               }
-               return 8;
-
-       case IBMACPI_THERMAL_NONE:
-       default:
-               return 0;
-       }
-}
-
-static int thermal_read(char *p)
-{
-       int len = 0;
-       int n, i;
-       struct ibm_thermal_sensors_struct t;
-
-       n = thermal_get_sensors(&t);
-       if (unlikely(n < 0))
-               return n;
-
-       len += sprintf(p + len, "temperatures:\t");
-
-       if (n > 0) {
-               for (i = 0; i < (n - 1); i++)
-                       len += sprintf(p + len, "%d ", t.temp[i] / 1000);
-               len += sprintf(p + len, "%d\n", t.temp[i] / 1000);
-       } else
-               len += sprintf(p + len, "not supported\n");
-
-       return len;
-}
-
-static u8 ecdump_regs[256];
-
-static int ecdump_read(char *p)
-{
-       int len = 0;
-       int i, j;
-       u8 v;
-
-       len += sprintf(p + len, "EC      "
-                      " +00 +01 +02 +03 +04 +05 +06 +07"
-                      " +08 +09 +0a +0b +0c +0d +0e +0f\n");
-       for (i = 0; i < 256; i += 16) {
-               len += sprintf(p + len, "EC 0x%02x:", i);
-               for (j = 0; j < 16; j++) {
-                       if (!acpi_ec_read(i + j, &v))
-                               break;
-                       if (v != ecdump_regs[i + j])
-                               len += sprintf(p + len, " *%02x", v);
-                       else
-                               len += sprintf(p + len, "  %02x", v);
-                       ecdump_regs[i + j] = v;
-               }
-               len += sprintf(p + len, "\n");
-               if (j != 16)
-                       break;
-       }
-
-       /* These are way too dangerous to advertise openly... */
-#if 0
-       len += sprintf(p + len, "commands:\t0x<offset> 0x<value>"
-                      " (<offset> is 00-ff, <value> is 00-ff)\n");
-       len += sprintf(p + len, "commands:\t0x<offset> <value>  "
-                      " (<offset> is 00-ff, <value> is 0-255)\n");
-#endif
-       return len;
-}
-
-static int ecdump_write(char *buf)
-{
-       char *cmd;
-       int i, v;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (sscanf(cmd, "0x%x 0x%x", &i, &v) == 2) {
-                       /* i and v set */
-               } else if (sscanf(cmd, "0x%x %u", &i, &v) == 2) {
-                       /* i and v set */
-               } else
-                       return -EINVAL;
-               if (i >= 0 && i < 256 && v >= 0 && v < 256) {
-                       if (!acpi_ec_write(i, v))
-                               return -EIO;
-               } else
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int brightness_offset = 0x31;
-
-static int brightness_get(struct backlight_device *bd)
-{
-       u8 level;
-       if (!acpi_ec_read(brightness_offset, &level))
-               return -EIO;
-
-       level &= 0x7;
-
-       return level;
-}
-
-static int brightness_read(char *p)
-{
-       int len = 0;
-       int level;
-
-       if ((level = brightness_get(NULL)) < 0) {
-               len += sprintf(p + len, "level:\t\tunreadable\n");
-       } else {
-               len += sprintf(p + len, "level:\t\t%d\n", level & 0x7);
-               len += sprintf(p + len, "commands:\tup, down\n");
-               len += sprintf(p + len, "commands:\tlevel <level>"
-                              " (<level> is 0-7)\n");
-       }
-
-       return len;
-}
-
-#define BRIGHTNESS_UP  4
-#define BRIGHTNESS_DOWN        5
-
-static int brightness_set(int value)
-{
-       int cmos_cmd, inc, i;
-       int current_value = brightness_get(NULL);
-
-       value &= 7;
-
-       cmos_cmd = value > current_value ? BRIGHTNESS_UP : BRIGHTNESS_DOWN;
-       inc = value > current_value ? 1 : -1;
-       for (i = current_value; i != value; i += inc) {
-               if (!cmos_eval(cmos_cmd))
-                       return -EIO;
-               if (!acpi_ec_write(brightness_offset, i + inc))
-                       return -EIO;
-       }
-
-       return 0;
-}
-
-static int brightness_write(char *buf)
-{
-       int level;
-       int new_level;
-       char *cmd;
-
-       while ((cmd = next_cmd(&buf))) {
-               if ((level = brightness_get(NULL)) < 0)
-                       return level;
-               level &= 7;
-
-               if (strlencmp(cmd, "up") == 0) {
-                       new_level = level == 7 ? 7 : level + 1;
-               } else if (strlencmp(cmd, "down") == 0) {
-                       new_level = level == 0 ? 0 : level - 1;
-               } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
-                          new_level >= 0 && new_level <= 7) {
-                       /* new_level set */
-               } else
-                       return -EINVAL;
-
-               brightness_set(new_level);
-       }
-
-       return 0;
-}
-
-static int brightness_update_status(struct backlight_device *bd)
-{
-       return brightness_set(
-               (bd->props.fb_blank == FB_BLANK_UNBLANK &&
-                bd->props.power == FB_BLANK_UNBLANK) ?
-                               bd->props.brightness : 0);
-}
-
-static struct backlight_ops ibm_backlight_data = {
-        .get_brightness = brightness_get,
-        .update_status  = brightness_update_status,
-};
-
-static int brightness_init(void)
-{
-       int b;
-
-       b = brightness_get(NULL);
-       if (b < 0)
-               return b;
-
-       ibm_backlight_device = backlight_device_register("ibm", NULL, NULL,
-                                                        &ibm_backlight_data);
-       if (IS_ERR(ibm_backlight_device)) {
-               printk(IBM_ERR "Could not register backlight device\n");
-               return PTR_ERR(ibm_backlight_device);
-       }
-
-       ibm_backlight_device->props.max_brightness = 7;
-       ibm_backlight_device->props.brightness = b;
-       backlight_update_status(ibm_backlight_device);
-
-       return 0;
-}
-
-static void brightness_exit(void)
-{
-       if (ibm_backlight_device) {
-               backlight_device_unregister(ibm_backlight_device);
-               ibm_backlight_device = NULL;
-       }
-}
-
-static int volume_offset = 0x30;
-
-static int volume_read(char *p)
-{
-       int len = 0;
-       u8 level;
-
-       if (!acpi_ec_read(volume_offset, &level)) {
-               len += sprintf(p + len, "level:\t\tunreadable\n");
-       } else {
-               len += sprintf(p + len, "level:\t\t%d\n", level & 0xf);
-               len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6));
-               len += sprintf(p + len, "commands:\tup, down, mute\n");
-               len += sprintf(p + len, "commands:\tlevel <level>"
-                              " (<level> is 0-15)\n");
-       }
-
-       return len;
-}
-
-#define VOLUME_DOWN    0
-#define VOLUME_UP      1
-#define VOLUME_MUTE    2
-
-static int volume_write(char *buf)
-{
-       int cmos_cmd, inc, i;
-       u8 level, mute;
-       int new_level, new_mute;
-       char *cmd;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (!acpi_ec_read(volume_offset, &level))
-                       return -EIO;
-               new_mute = mute = level & 0x40;
-               new_level = level = level & 0xf;
-
-               if (strlencmp(cmd, "up") == 0) {
-                       if (mute)
-                               new_mute = 0;
-                       else
-                               new_level = level == 15 ? 15 : level + 1;
-               } else if (strlencmp(cmd, "down") == 0) {
-                       if (mute)
-                               new_mute = 0;
-                       else
-                               new_level = level == 0 ? 0 : level - 1;
-               } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
-                          new_level >= 0 && new_level <= 15) {
-                       /* new_level set */
-               } else if (strlencmp(cmd, "mute") == 0) {
-                       new_mute = 0x40;
-               } else
-                       return -EINVAL;
-
-               if (new_level != level) {       /* mute doesn't change */
-                       cmos_cmd = new_level > level ? VOLUME_UP : VOLUME_DOWN;
-                       inc = new_level > level ? 1 : -1;
-
-                       if (mute && (!cmos_eval(cmos_cmd) ||
-                                    !acpi_ec_write(volume_offset, level)))
-                               return -EIO;
-
-                       for (i = level; i != new_level; i += inc)
-                               if (!cmos_eval(cmos_cmd) ||
-                                   !acpi_ec_write(volume_offset, i + inc))
-                                       return -EIO;
-
-                       if (mute && (!cmos_eval(VOLUME_MUTE) ||
-                                    !acpi_ec_write(volume_offset,
-                                                   new_level + mute)))
-                               return -EIO;
-               }
-
-               if (new_mute != mute) { /* level doesn't change */
-                       cmos_cmd = new_mute ? VOLUME_MUTE : VOLUME_UP;
-
-                       if (!cmos_eval(cmos_cmd) ||
-                           !acpi_ec_write(volume_offset, level + new_mute))
-                               return -EIO;
-               }
-       }
-
-       return 0;
-}
-
-static enum fan_status_access_mode fan_status_access_mode;
-static enum fan_control_access_mode fan_control_access_mode;
-static enum fan_control_commands fan_control_commands;
-
-static int fan_control_status_known;
-static u8 fan_control_initial_status;
-
-static void fan_watchdog_fire(struct work_struct *ignored);
-static int fan_watchdog_maxinterval;
-static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire);
-
-static int fan_init(void)
-{
-       fan_status_access_mode = IBMACPI_FAN_NONE;
-       fan_control_access_mode = IBMACPI_FAN_WR_NONE;
-       fan_control_commands = 0;
-       fan_control_status_known = 1;
-       fan_watchdog_maxinterval = 0;
-
-       if (gfan_handle) {
-               /* 570, 600e/x, 770e, 770x */
-               fan_status_access_mode = IBMACPI_FAN_RD_ACPI_GFAN;
-       } else {
-               /* all other ThinkPads: note that even old-style
-                * ThinkPad ECs supports the fan control register */
-               if (likely(acpi_ec_read(fan_status_offset,
-                                       &fan_control_initial_status))) {
-                       fan_status_access_mode = IBMACPI_FAN_RD_TPEC;
-
-                       /* In some ThinkPads, neither the EC nor the ACPI
-                        * DSDT initialize the fan status, and it ends up
-                        * being set to 0x07 when it *could* be either
-                        * 0x07 or 0x80.
-                        *
-                        * Enable for TP-1Y (T43), TP-78 (R51e),
-                        * TP-76 (R52), TP-70 (T43, R52), which are known
-                        * to be buggy. */
-                       if (fan_control_initial_status == 0x07 &&
-                           ibm_thinkpad_ec_found &&
-                           ((ibm_thinkpad_ec_found[0] == '1' &&
-                             ibm_thinkpad_ec_found[1] == 'Y') ||
-                            (ibm_thinkpad_ec_found[0] == '7' &&
-                             (ibm_thinkpad_ec_found[1] == '6' ||
-                              ibm_thinkpad_ec_found[1] == '8' ||
-                              ibm_thinkpad_ec_found[1] == '0'))
-                           )) {
-                               printk(IBM_NOTICE
-                                      "fan_init: initial fan status is "
-                                      "unknown, assuming it is in auto "
-                                      "mode\n");
-                               fan_control_status_known = 0;
-                       }
-               } else {
-                       printk(IBM_ERR
-                              "ThinkPad ACPI EC access misbehaving, "
-                              "fan status and control unavailable\n");
-                       return 0;
-               }
-       }
-
-       if (sfan_handle) {
-               /* 570, 770x-JL */
-               fan_control_access_mode = IBMACPI_FAN_WR_ACPI_SFAN;
-               fan_control_commands |=
-                   IBMACPI_FAN_CMD_LEVEL | IBMACPI_FAN_CMD_ENABLE;
-       } else {
-               if (!gfan_handle) {
-                       /* gfan without sfan means no fan control */
-                       /* all other models implement TP EC 0x2f control */
-
-                       if (fans_handle) {
-                               /* X31, X40, X41 */
-                               fan_control_access_mode =
-                                   IBMACPI_FAN_WR_ACPI_FANS;
-                               fan_control_commands |=
-                                   IBMACPI_FAN_CMD_SPEED |
-                                   IBMACPI_FAN_CMD_LEVEL |
-                                   IBMACPI_FAN_CMD_ENABLE;
-                       } else {
-                               fan_control_access_mode = IBMACPI_FAN_WR_TPEC;
-                               fan_control_commands |=
-                                   IBMACPI_FAN_CMD_LEVEL |
-                                   IBMACPI_FAN_CMD_ENABLE;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int fan_get_status(u8 *status)
-{
-       u8 s;
-
-       /* TODO:
-        * Add IBMACPI_FAN_RD_ACPI_FANS ? */
-
-       switch (fan_status_access_mode) {
-       case IBMACPI_FAN_RD_ACPI_GFAN:
-               /* 570, 600e/x, 770e, 770x */
-
-               if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
-                       return -EIO;
-
-               if (likely(status))
-                       *status = s & 0x07;
-
-               break;
-
-       case IBMACPI_FAN_RD_TPEC:
-               /* all except 570, 600e/x, 770e, 770x */
-               if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
-                       return -EIO;
-
-               if (likely(status))
-                       *status = s;
-
-               break;
-
-       default:
-               return -ENXIO;
-       }
-
-       return 0;
-}
-
-static int fan_get_speed(unsigned int *speed)
-{
-       u8 hi, lo;
-
-       switch (fan_status_access_mode) {
-       case IBMACPI_FAN_RD_TPEC:
-               /* all except 570, 600e/x, 770e, 770x */
-               if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
-                            !acpi_ec_read(fan_rpm_offset + 1, &hi)))
-                       return -EIO;
-
-               if (likely(speed))
-                       *speed = (hi << 8) | lo;
-
-               break;
-
-       default:
-               return -ENXIO;
-       }
-
-       return 0;
-}
-
-static void fan_exit(void)
-{
-       cancel_delayed_work(&fan_watchdog_task);
-       flush_scheduled_work();
-}
-
-static void fan_watchdog_reset(void)
-{
-       static int fan_watchdog_active = 0;
-
-       if (fan_watchdog_active)
-               cancel_delayed_work(&fan_watchdog_task);
-
-       if (fan_watchdog_maxinterval > 0) {
-               fan_watchdog_active = 1;
-               if (!schedule_delayed_work(&fan_watchdog_task,
-                               msecs_to_jiffies(fan_watchdog_maxinterval
-                                                * 1000))) {
-                       printk(IBM_ERR "failed to schedule the fan watchdog, "
-                              "watchdog will not trigger\n");
-               }
-       } else
-               fan_watchdog_active = 0;
-}
-
-static int fan_read(char *p)
-{
-       int len = 0;
-       int rc;
-       u8 status;
-       unsigned int speed = 0;
-
-       switch (fan_status_access_mode) {
-       case IBMACPI_FAN_RD_ACPI_GFAN:
-               /* 570, 600e/x, 770e, 770x */
-               if ((rc = fan_get_status(&status)) < 0)
-                       return rc;
-
-               len += sprintf(p + len, "status:\t\t%s\n"
-                              "level:\t\t%d\n",
-                              (status != 0) ? "enabled" : "disabled", status);
-               break;
-
-       case IBMACPI_FAN_RD_TPEC:
-               /* all except 570, 600e/x, 770e, 770x */
-               if ((rc = fan_get_status(&status)) < 0)
-                       return rc;
-
-               if (unlikely(!fan_control_status_known)) {
-                       if (status != fan_control_initial_status)
-                               fan_control_status_known = 1;
-                       else
-                               /* Return most likely status. In fact, it
-                                * might be the only possible status */
-                               status = IBMACPI_FAN_EC_AUTO;
-               }
-
-               len += sprintf(p + len, "status:\t\t%s\n",
-                              (status != 0) ? "enabled" : "disabled");
-
-               /* No ThinkPad boots on disengaged mode, we can safely
-                * assume the tachometer is online if fan control status
-                * was unknown */
-               if ((rc = fan_get_speed(&speed)) < 0)
-                       return rc;
-
-               len += sprintf(p + len, "speed:\t\t%d\n", speed);
-
-               if (status & IBMACPI_FAN_EC_DISENGAGED)
-                       /* Disengaged mode takes precedence */
-                       len += sprintf(p + len, "level:\t\tdisengaged\n");
-               else if (status & IBMACPI_FAN_EC_AUTO)
-                       len += sprintf(p + len, "level:\t\tauto\n");
-               else
-                       len += sprintf(p + len, "level:\t\t%d\n", status);
-               break;
-
-       case IBMACPI_FAN_NONE:
-       default:
-               len += sprintf(p + len, "status:\t\tnot supported\n");
-       }
-
-       if (fan_control_commands & IBMACPI_FAN_CMD_LEVEL) {
-               len += sprintf(p + len, "commands:\tlevel <level>");
-
-               switch (fan_control_access_mode) {
-               case IBMACPI_FAN_WR_ACPI_SFAN:
-                       len += sprintf(p + len, " (<level> is 0-7)\n");
-                       break;
-
-               default:
-                       len += sprintf(p + len, " (<level> is 0-7, "
-                                      "auto, disengaged)\n");
-                       break;
-               }
-       }
-
-       if (fan_control_commands & IBMACPI_FAN_CMD_ENABLE)
-               len += sprintf(p + len, "commands:\tenable, disable\n"
-                              "commands:\twatchdog <timeout> (<timeout> is 0 (off), "
-                              "1-120 (seconds))\n");
-
-       if (fan_control_commands & IBMACPI_FAN_CMD_SPEED)
-               len += sprintf(p + len, "commands:\tspeed <speed>"
-                              " (<speed> is 0-65535)\n");
-
-       return len;
-}
-
-static int fan_set_level(int level)
-{
-       switch (fan_control_access_mode) {
-       case IBMACPI_FAN_WR_ACPI_SFAN:
-               if (level >= 0 && level <= 7) {
-                       if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
-                               return -EIO;
-               } else
-                       return -EINVAL;
-               break;
-
-       case IBMACPI_FAN_WR_ACPI_FANS:
-       case IBMACPI_FAN_WR_TPEC:
-               if ((level != IBMACPI_FAN_EC_AUTO) &&
-                   (level != IBMACPI_FAN_EC_DISENGAGED) &&
-                   ((level < 0) || (level > 7)))
-                       return -EINVAL;
-
-               if (!acpi_ec_write(fan_status_offset, level))
-                       return -EIO;
-               else
-                       fan_control_status_known = 1;
-               break;
-
-       default:
-               return -ENXIO;
-       }
-       return 0;
-}
-
-static int fan_set_enable(void)
-{
-       u8 s;
-       int rc;
-
-       switch (fan_control_access_mode) {
-       case IBMACPI_FAN_WR_ACPI_FANS:
-       case IBMACPI_FAN_WR_TPEC:
-               if ((rc = fan_get_status(&s)) < 0)
-                       return rc;
-
-               /* Don't go out of emergency fan mode */
-               if (s != 7)
-                       s = IBMACPI_FAN_EC_AUTO;
-
-               if (!acpi_ec_write(fan_status_offset, s))
-                       return -EIO;
-               else
-                       fan_control_status_known = 1;
-               break;
-
-       case IBMACPI_FAN_WR_ACPI_SFAN:
-               if ((rc = fan_get_status(&s)) < 0)
-                       return rc;
-
-               s &= 0x07;
-
-               /* Set fan to at least level 4 */
-               if (s < 4)
-                       s = 4;
-
-               if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
-                       return -EIO;
-               break;
-
-       default:
-               return -ENXIO;
-       }
-       return 0;
-}
-
-static int fan_set_disable(void)
-{
-       switch (fan_control_access_mode) {
-       case IBMACPI_FAN_WR_ACPI_FANS:
-       case IBMACPI_FAN_WR_TPEC:
-               if (!acpi_ec_write(fan_status_offset, 0x00))
-                       return -EIO;
-               else
-                       fan_control_status_known = 1;
-               break;
-
-       case IBMACPI_FAN_WR_ACPI_SFAN:
-               if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00))
-                       return -EIO;
-               break;
-
-       default:
-               return -ENXIO;
-       }
-       return 0;
-}
-
-static int fan_set_speed(int speed)
-{
-       switch (fan_control_access_mode) {
-       case IBMACPI_FAN_WR_ACPI_FANS:
-               if (speed >= 0 && speed <= 65535) {
-                       if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
-                                       speed, speed, speed))
-                               return -EIO;
-               } else
-                       return -EINVAL;
-               break;
-
-       default:
-               return -ENXIO;
-       }
-       return 0;
-}
-
-static int fan_write_cmd_level(const char *cmd, int *rc)
-{
-       int level;
-
-       if (strlencmp(cmd, "level auto") == 0)
-               level = IBMACPI_FAN_EC_AUTO;
-       else if (strlencmp(cmd, "level disengaged") == 0)
-               level = IBMACPI_FAN_EC_DISENGAGED;
-       else if (sscanf(cmd, "level %d", &level) != 1)
-               return 0;
-
-       if ((*rc = fan_set_level(level)) == -ENXIO)
-               printk(IBM_ERR "level command accepted for unsupported "
-                      "access mode %d", fan_control_access_mode);
-
-       return 1;
-}
-
-static int fan_write_cmd_enable(const char *cmd, int *rc)
-{
-       if (strlencmp(cmd, "enable") != 0)
-               return 0;
-
-       if ((*rc = fan_set_enable()) == -ENXIO)
-               printk(IBM_ERR "enable command accepted for unsupported "
-                      "access mode %d", fan_control_access_mode);
-
-       return 1;
-}
-
-static int fan_write_cmd_disable(const char *cmd, int *rc)
-{
-       if (strlencmp(cmd, "disable") != 0)
-               return 0;
-
-       if ((*rc = fan_set_disable()) == -ENXIO)
-               printk(IBM_ERR "disable command accepted for unsupported "
-                      "access mode %d", fan_control_access_mode);
-
-       return 1;
-}
-
-static int fan_write_cmd_speed(const char *cmd, int *rc)
-{
-       int speed;
-
-       /* TODO:
-        * Support speed <low> <medium> <high> ? */
-
-       if (sscanf(cmd, "speed %d", &speed) != 1)
-               return 0;
-
-       if ((*rc = fan_set_speed(speed)) == -ENXIO)
-               printk(IBM_ERR "speed command accepted for unsupported "
-                      "access mode %d", fan_control_access_mode);
-
-       return 1;
-}
-
-static int fan_write_cmd_watchdog(const char *cmd, int *rc)
-{
-       int interval;
-
-       if (sscanf(cmd, "watchdog %d", &interval) != 1)
-               return 0;
-
-       if (interval < 0 || interval > 120)
-               *rc = -EINVAL;
-       else
-               fan_watchdog_maxinterval = interval;
-
-       return 1;
-}
-
-static int fan_write(char *buf)
-{
-       char *cmd;
-       int rc = 0;
-
-       while (!rc && (cmd = next_cmd(&buf))) {
-               if (!((fan_control_commands & IBMACPI_FAN_CMD_LEVEL) &&
-                     fan_write_cmd_level(cmd, &rc)) &&
-                   !((fan_control_commands & IBMACPI_FAN_CMD_ENABLE) &&
-                     (fan_write_cmd_enable(cmd, &rc) ||
-                      fan_write_cmd_disable(cmd, &rc) ||
-                      fan_write_cmd_watchdog(cmd, &rc))) &&
-                   !((fan_control_commands & IBMACPI_FAN_CMD_SPEED) &&
-                     fan_write_cmd_speed(cmd, &rc))
-                   )
-                       rc = -EINVAL;
-               else if (!rc)
-                       fan_watchdog_reset();
-       }
-
-       return rc;
-}
-
-static void fan_watchdog_fire(struct work_struct *ignored)
-{
-       printk(IBM_NOTICE "fan watchdog: enabling fan\n");
-       if (fan_set_enable()) {
-               printk(IBM_ERR "fan watchdog: error while enabling fan\n");
-               /* reschedule for later */
-               fan_watchdog_reset();
-       }
-}
-
-static struct ibm_struct ibms[] = {
-       {
-        .name = "driver",
-        .init = ibm_acpi_driver_init,
-        .read = driver_read,
-        },
-       {
-        .name = "hotkey",
-        .hid = IBM_HKEY_HID,
-        .init = hotkey_init,
-        .read = hotkey_read,
-        .write = hotkey_write,
-        .exit = hotkey_exit,
-        .notify = hotkey_notify,
-        .handle = &hkey_handle,
-        .type = ACPI_DEVICE_NOTIFY,
-        },
-       {
-        .name = "bluetooth",
-        .init = bluetooth_init,
-        .read = bluetooth_read,
-        .write = bluetooth_write,
-        },
-       {
-        .name = "wan",
-        .init = wan_init,
-        .read = wan_read,
-        .write = wan_write,
-        .experimental = 1,
-        },
-       {
-        .name = "video",
-        .init = video_init,
-        .read = video_read,
-        .write = video_write,
-        .exit = video_exit,
-        },
-       {
-        .name = "light",
-        .init = light_init,
-        .read = light_read,
-        .write = light_write,
-        },
-#ifdef CONFIG_ACPI_IBM_DOCK
-       {
-        .name = "dock",
-        .read = dock_read,
-        .write = dock_write,
-        .notify = dock_notify,
-        .handle = &dock_handle,
-        .type = ACPI_SYSTEM_NOTIFY,
-        },
-       {
-        .name = "dock",
-        .hid = IBM_PCI_HID,
-        .notify = dock_notify,
-        .handle = &pci_handle,
-        .type = ACPI_SYSTEM_NOTIFY,
-        },
-#endif
-#ifdef CONFIG_ACPI_IBM_BAY
-       {
-        .name = "bay",
-        .init = bay_init,
-        .read = bay_read,
-        .write = bay_write,
-        .notify = bay_notify,
-        .handle = &bay_handle,
-        .type = ACPI_SYSTEM_NOTIFY,
-        },
-#endif /* CONFIG_ACPI_IBM_BAY */
-       {
-        .name = "cmos",
-        .read = cmos_read,
-        .write = cmos_write,
-        },
-       {
-        .name = "led",
-        .init = led_init,
-        .read = led_read,
-        .write = led_write,
-        },
-       {
-        .name = "beep",
-        .read = beep_read,
-        .write = beep_write,
-        },
-       {
-        .name = "thermal",
-        .init = thermal_init,
-        .read = thermal_read,
-        },
-       {
-        .name = "ecdump",
-        .read = ecdump_read,
-        .write = ecdump_write,
-        .experimental = 1,
-        },
-       {
-        .name = "brightness",
-        .read = brightness_read,
-        .write = brightness_write,
-        .init = brightness_init,
-        .exit = brightness_exit,
-        },
-       {
-        .name = "volume",
-        .read = volume_read,
-        .write = volume_write,
-        },
-       {
-        .name = "fan",
-        .read = fan_read,
-        .write = fan_write,
-        .init = fan_init,
-        .exit = fan_exit,
-        .experimental = 1,
-        },
-};
-
-static int dispatch_read(char *page, char **start, off_t off, int count,
-                        int *eof, void *data)
-{
-       struct ibm_struct *ibm = data;
-       int len;
-
-       if (!ibm || !ibm->read)
-               return -EINVAL;
-
-       len = ibm->read(page);
-       if (len < 0)
-               return len;
-
-       if (len <= off + count)
-               *eof = 1;
-       *start = page + off;
-       len -= off;
-       if (len > count)
-               len = count;
-       if (len < 0)
-               len = 0;
-
-       return len;
-}
-
-static int dispatch_write(struct file *file, const char __user * userbuf,
-                         unsigned long count, void *data)
-{
-       struct ibm_struct *ibm = data;
-       char *kernbuf;
-       int ret;
-
-       if (!ibm || !ibm->write)
-               return -EINVAL;
-
-       kernbuf = kmalloc(count + 2, GFP_KERNEL);
-       if (!kernbuf)
-               return -ENOMEM;
-
-       if (copy_from_user(kernbuf, userbuf, count)) {
-               kfree(kernbuf);
-               return -EFAULT;
-       }
-
-       kernbuf[count] = 0;
-       strcat(kernbuf, ",");
-       ret = ibm->write(kernbuf);
-       if (ret == 0)
-               ret = count;
-
-       kfree(kernbuf);
-
-       return ret;
-}
-
-static void dispatch_notify(acpi_handle handle, u32 event, void *data)
-{
-       struct ibm_struct *ibm = data;
-
-       if (!ibm || !ibm->notify)
-               return;
-
-       ibm->notify(ibm, event);
-}
-
-static int __init setup_notify(struct ibm_struct *ibm)
-{
-       acpi_status status;
-       int ret;
-
-       if (!*ibm->handle)
-               return 0;
-
-       ret = acpi_bus_get_device(*ibm->handle, &ibm->device);
-       if (ret < 0) {
-               printk(IBM_ERR "%s device not present\n", ibm->name);
-               return -ENODEV;
-       }
-
-       acpi_driver_data(ibm->device) = ibm;
-       sprintf(acpi_device_class(ibm->device), "%s/%s", IBM_NAME, ibm->name);
-
-       status = acpi_install_notify_handler(*ibm->handle, ibm->type,
-                                            dispatch_notify, ibm);
-       if (ACPI_FAILURE(status)) {
-               if (status == AE_ALREADY_EXISTS) {
-                       printk(IBM_NOTICE "another device driver is already handling %s events\n",
-                               ibm->name);
-               } else {
-                       printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n",
-                               ibm->name, status);
-               }
-               return -ENODEV;
-       }
-       ibm->notify_installed = 1;
-       return 0;
-}
-
-static int __init ibm_device_add(struct acpi_device *device)
-{
-       return 0;
-}
-
-static int __init register_driver(struct ibm_struct *ibm)
-{
-       int ret;
-
-       ibm->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL);
-       if (!ibm->driver) {
-               printk(IBM_ERR "kmalloc(ibm->driver) failed\n");
-               return -1;
-       }
-
-       sprintf(ibm->driver->name, "%s_%s", IBM_NAME, ibm->name);
-       ibm->driver->ids = ibm->hid;
-       ibm->driver->ops.add = &ibm_device_add;
-
-       ret = acpi_bus_register_driver(ibm->driver);
-       if (ret < 0) {
-               printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n",
-                      ibm->hid, ret);
-               kfree(ibm->driver);
-       }
-
-       return ret;
-}
-
-static void ibm_exit(struct ibm_struct *ibm);
-
-static int __init ibm_init(struct ibm_struct *ibm)
-{
-       int ret;
-       struct proc_dir_entry *entry;
-
-       if (ibm->experimental && !experimental)
-               return 0;
-
-       if (ibm->hid) {
-               ret = register_driver(ibm);
-               if (ret < 0)
-                       return ret;
-               ibm->driver_registered = 1;
-       }
-
-       if (ibm->init) {
-               ret = ibm->init();
-               if (ret != 0)
-                       return ret;
-               ibm->init_called = 1;
-       }
-
-       if (ibm->read) {
-               entry = create_proc_entry(ibm->name,
-                                         S_IFREG | S_IRUGO | S_IWUSR,
-                                         proc_dir);
-               if (!entry) {
-                       printk(IBM_ERR "unable to create proc entry %s\n",
-                              ibm->name);
-                       return -ENODEV;
-               }
-               entry->owner = THIS_MODULE;
-               entry->data = ibm;
-               entry->read_proc = &dispatch_read;
-               if (ibm->write)
-                       entry->write_proc = &dispatch_write;
-               ibm->proc_created = 1;
-       }
-
-       if (ibm->notify) {
-               ret = setup_notify(ibm);
-               if (ret == -ENODEV) {
-                       printk(IBM_NOTICE "disabling subdriver %s\n",
-                               ibm->name);
-                       ibm_exit(ibm);
-                       return 0;
-               }
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static void ibm_exit(struct ibm_struct *ibm)
-{
-       if (ibm->notify_installed)
-               acpi_remove_notify_handler(*ibm->handle, ibm->type,
-                                          dispatch_notify);
-
-       if (ibm->proc_created)
-               remove_proc_entry(ibm->name, proc_dir);
-
-       if (ibm->init_called && ibm->exit)
-               ibm->exit();
-
-       if (ibm->driver_registered) {
-               acpi_bus_unregister_driver(ibm->driver);
-               kfree(ibm->driver);
-       }
-}
-
-static void __init ibm_handle_init(char *name,
-                                  acpi_handle * handle, acpi_handle parent,
-                                  char **paths, int num_paths, char **path)
-{
-       int i;
-       acpi_status status;
-
-       for (i = 0; i < num_paths; i++) {
-               status = acpi_get_handle(parent, paths[i], handle);
-               if (ACPI_SUCCESS(status)) {
-                       *path = paths[i];
-                       return;
-               }
-       }
-
-       *handle = NULL;
-}
-
-#define IBM_HANDLE_INIT(object)                                                \
-       ibm_handle_init(#object, &object##_handle, *object##_parent,    \
-               object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
-
-static int __init set_ibm_param(const char *val, struct kernel_param *kp)
-{
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(ibms); i++)
-               if (strcmp(ibms[i].name, kp->name) == 0 && ibms[i].write) {
-                       if (strlen(val) > sizeof(ibms[i].param) - 2)
-                               return -ENOSPC;
-                       strcpy(ibms[i].param, val);
-                       strcat(ibms[i].param, ",");
-                       return 0;
-               }
-
-       return -EINVAL;
-}
-
-#define IBM_PARAM(feature) \
-       module_param_call(feature, set_ibm_param, NULL, NULL, 0)
-
-IBM_PARAM(hotkey);
-IBM_PARAM(bluetooth);
-IBM_PARAM(video);
-IBM_PARAM(light);
-#ifdef CONFIG_ACPI_IBM_DOCK
-IBM_PARAM(dock);
-#endif
-#ifdef CONFIG_ACPI_IBM_BAY
-IBM_PARAM(bay);
-#endif /* CONFIG_ACPI_IBM_BAY */
-IBM_PARAM(cmos);
-IBM_PARAM(led);
-IBM_PARAM(beep);
-IBM_PARAM(ecdump);
-IBM_PARAM(brightness);
-IBM_PARAM(volume);
-IBM_PARAM(fan);
-
-static void acpi_ibm_exit(void)
-{
-       int i;
-
-       for (i = ARRAY_SIZE(ibms) - 1; i >= 0; i--)
-               ibm_exit(&ibms[i]);
-
-       if (proc_dir)
-               remove_proc_entry(IBM_DIR, acpi_root_dir);
-
-       if (ibm_thinkpad_ec_found)
-               kfree(ibm_thinkpad_ec_found);
-}
-
-static char* __init check_dmi_for_ec(void)
-{
-       struct dmi_device *dev = NULL;
-       char ec_fw_string[18];
-
-       /*
-        * ThinkPad T23 or newer, A31 or newer, R50e or newer,
-        * X32 or newer, all Z series;  Some models must have an
-        * up-to-date BIOS or they will not be detected.
-        *
-        * See http://thinkwiki.org/wiki/List_of_DMI_IDs
-        */
-       while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
-               if (sscanf(dev->name,
-                          "IBM ThinkPad Embedded Controller -[%17c",
-                          ec_fw_string) == 1) {
-                       ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
-                       ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
-                       return kstrdup(ec_fw_string, GFP_KERNEL);
-               }
-       }
-       return NULL;
-}
-
-static int __init acpi_ibm_init(void)
-{
-       int ret, i;
-
-       if (acpi_disabled)
-               return -ENODEV;
-
-       /* ec is required because many other handles are relative to it */
-       IBM_HANDLE_INIT(ec);
-       if (!ec_handle) {
-               printk(IBM_ERR "ec object not found\n");
-               return -ENODEV;
-       }
-
-       /* Models with newer firmware report the EC in DMI */
-       ibm_thinkpad_ec_found = check_dmi_for_ec();
-
-       /* these handles are not required */
-       IBM_HANDLE_INIT(vid);
-       IBM_HANDLE_INIT(vid2);
-       IBM_HANDLE_INIT(ledb);
-       IBM_HANDLE_INIT(led);
-       IBM_HANDLE_INIT(hkey);
-       IBM_HANDLE_INIT(lght);
-       IBM_HANDLE_INIT(cmos);
-#ifdef CONFIG_ACPI_IBM_DOCK
-       IBM_HANDLE_INIT(dock);
-#endif
-       IBM_HANDLE_INIT(pci);
-#ifdef CONFIG_ACPI_IBM_BAY
-       IBM_HANDLE_INIT(bay);
-       if (bay_handle)
-               IBM_HANDLE_INIT(bay_ej);
-       IBM_HANDLE_INIT(bay2);
-       if (bay2_handle)
-               IBM_HANDLE_INIT(bay2_ej);
-#endif /* CONFIG_ACPI_IBM_BAY */
-       IBM_HANDLE_INIT(beep);
-       IBM_HANDLE_INIT(ecrd);
-       IBM_HANDLE_INIT(ecwr);
-       IBM_HANDLE_INIT(fans);
-       IBM_HANDLE_INIT(gfan);
-       IBM_HANDLE_INIT(sfan);
-
-       proc_dir = proc_mkdir(IBM_DIR, acpi_root_dir);
-       if (!proc_dir) {
-               printk(IBM_ERR "unable to create proc dir %s", IBM_DIR);
-               acpi_ibm_exit();
-               return -ENODEV;
-       }
-       proc_dir->owner = THIS_MODULE;
-
-       for (i = 0; i < ARRAY_SIZE(ibms); i++) {
-               ret = ibm_init(&ibms[i]);
-               if (ret >= 0 && *ibms[i].param)
-                       ret = ibms[i].write(ibms[i].param);
-               if (ret < 0) {
-                       acpi_ibm_exit();
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-module_init(acpi_ibm_init);
-module_exit(acpi_ibm_exit);
index 99d1516..f7de02a 100644 (file)
@@ -70,8 +70,6 @@
 #define ACPI_PROCESSOR_LIMIT_USER      0
 #define ACPI_PROCESSOR_LIMIT_THERMAL   1
 
-#define ACPI_STA_PRESENT 0x00000001
-
 #define _COMPONENT             ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_core");
 
@@ -779,7 +777,7 @@ static int is_processor_present(acpi_handle handle)
 
 
        status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-       if (ACPI_FAILURE(status) || !(sta & ACPI_STA_PRESENT)) {
+       if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) {
                ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
                return 0;
        }
index cdf7894..ae0654c 100644 (file)
 #include <asm/apic.h>
 #endif
 
-/*
- * Include the apic definitions for x86 to have the APIC timer related defines
- * available also for UP (on SMP it gets magically included via linux/smp.h).
- */
-#ifdef CONFIG_X86
-#include <asm/apic.h>
-#endif
-
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
index 59640d9..c1bae10 100644 (file)
 #include <linux/seq_file.h>
 #include <asm/uaccess.h>
 #include <linux/acpi.h>
-#include <linux/i2c.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
 #include <linux/delay.h>
 
-#include "i2c_ec.h"
-
-#define        DEF_CAPACITY_UNIT       3
-#define        MAH_CAPACITY_UNIT       1
-#define        MWH_CAPACITY_UNIT       2
-#define        CAPACITY_UNIT           DEF_CAPACITY_UNIT
-
-#define        REQUEST_UPDATE_MODE     1
-#define        QUEUE_UPDATE_MODE       2
-
-#define        DATA_TYPE_COMMON        0
-#define        DATA_TYPE_INFO          1
-#define        DATA_TYPE_STATE         2
-#define        DATA_TYPE_ALARM         3
-#define        DATA_TYPE_AC_STATE      4
-
-extern struct proc_dir_entry *acpi_lock_ac_dir(void);
-extern struct proc_dir_entry *acpi_lock_battery_dir(void);
-extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
-extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
-
 #define ACPI_SBS_COMPONENT             0x00080000
 #define ACPI_SBS_CLASS                 "sbs"
 #define ACPI_AC_CLASS                  "ac_adapter"
@@ -74,39 +54,75 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
 
 #define _COMPONENT                     ACPI_SBS_COMPONENT
 
-#define        MAX_SBS_BAT                     4
-#define        MAX_SMBUS_ERR                   1
-
 ACPI_MODULE_NAME("sbs");
 
 MODULE_AUTHOR("Rich Townsend");
 MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
 MODULE_LICENSE("GPL");
 
-static struct semaphore sbs_sem;
+#define        xmsleep(t)      msleep(t)
+
+#define ACPI_EC_SMB_PRTCL      0x00    /* protocol, PEC */
+
+#define ACPI_EC_SMB_STS                0x01    /* status */
+#define ACPI_EC_SMB_ADDR       0x02    /* address */
+#define ACPI_EC_SMB_CMD                0x03    /* command */
+#define ACPI_EC_SMB_DATA       0x04    /* 32 data registers */
+#define ACPI_EC_SMB_BCNT       0x24    /* number of data bytes */
 
-#define        UPDATE_MODE             QUEUE_UPDATE_MODE
-/* REQUEST_UPDATE_MODE  QUEUE_UPDATE_MODE */
-#define        UPDATE_INFO_MODE        0
-#define        UPDATE_TIME             60
-#define        UPDATE_TIME2            0
+#define ACPI_EC_SMB_STS_DONE   0x80
+#define ACPI_EC_SMB_STS_STATUS 0x1f
 
-static int capacity_mode = CAPACITY_UNIT;
-static int update_mode = UPDATE_MODE;
-static int update_info_mode = UPDATE_INFO_MODE;
-static int update_time = UPDATE_TIME;
-static int update_time2 = UPDATE_TIME2;
+#define ACPI_EC_SMB_PRTCL_WRITE                0x00
+#define ACPI_EC_SMB_PRTCL_READ         0x01
+#define ACPI_EC_SMB_PRTCL_WORD_DATA    0x08
+#define ACPI_EC_SMB_PRTCL_BLOCK_DATA   0x0a
 
-module_param(capacity_mode, int, 0);
-module_param(update_mode, int, 0);
-module_param(update_info_mode, int, 0);
-module_param(update_time, int, 0);
-module_param(update_time2, int, 0);
+#define ACPI_EC_SMB_TRANSACTION_SLEEP  1
+#define ACPI_EC_SMB_ACCESS_SLEEP1      1
+#define ACPI_EC_SMB_ACCESS_SLEEP2      10
+
+#define        DEF_CAPACITY_UNIT       3
+#define        MAH_CAPACITY_UNIT       1
+#define        MWH_CAPACITY_UNIT       2
+#define        CAPACITY_UNIT           DEF_CAPACITY_UNIT
+
+#define        REQUEST_UPDATE_MODE     1
+#define        QUEUE_UPDATE_MODE       2
+
+#define        DATA_TYPE_COMMON        0
+#define        DATA_TYPE_INFO          1
+#define        DATA_TYPE_STATE         2
+#define        DATA_TYPE_ALARM         3
+#define        DATA_TYPE_AC_STATE      4
+
+extern struct proc_dir_entry *acpi_lock_ac_dir(void);
+extern struct proc_dir_entry *acpi_lock_battery_dir(void);
+extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
+extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
+
+#define        MAX_SBS_BAT                     4
+#define ACPI_SBS_BLOCK_MAX             32
+
+#define ACPI_SBS_SMBUS_READ            1
+#define ACPI_SBS_SMBUS_WRITE           2
+
+#define ACPI_SBS_WORD_DATA             1
+#define ACPI_SBS_BLOCK_DATA            2
+
+#define        UPDATE_DELAY    10
+
+/* 0 - every time, > 0 - by update_time */
+static unsigned int update_time = 120;
+
+static unsigned int capacity_mode = CAPACITY_UNIT;
+
+module_param(update_time, uint, 0644);
+module_param(capacity_mode, uint, 0444);
 
 static int acpi_sbs_add(struct acpi_device *device);
 static int acpi_sbs_remove(struct acpi_device *device, int type);
-static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus);
-static void acpi_sbs_update_queue(void *data);
+static int acpi_sbs_resume(struct acpi_device *device);
 
 static struct acpi_driver acpi_sbs_driver = {
        .name = "sbs",
@@ -115,9 +131,14 @@ static struct acpi_driver acpi_sbs_driver = {
        .ops = {
                .add = acpi_sbs_add,
                .remove = acpi_sbs_remove,
+               .resume = acpi_sbs_resume,
                },
 };
 
+struct acpi_ac {
+       int ac_present;
+};
+
 struct acpi_battery_info {
        int capacity_mode;
        s16 full_charge_capacity;
@@ -126,18 +147,16 @@ struct acpi_battery_info {
        int vscale;
        int ipscale;
        s16 serial_number;
-       char manufacturer_name[I2C_SMBUS_BLOCK_MAX + 3];
-       char device_name[I2C_SMBUS_BLOCK_MAX + 3];
-       char device_chemistry[I2C_SMBUS_BLOCK_MAX + 3];
+       char manufacturer_name[ACPI_SBS_BLOCK_MAX + 3];
+       char device_name[ACPI_SBS_BLOCK_MAX + 3];
+       char device_chemistry[ACPI_SBS_BLOCK_MAX + 3];
 };
 
 struct acpi_battery_state {
        s16 voltage;
        s16 amperage;
        s16 remaining_capacity;
-       s16 average_time_to_empty;
-       s16 average_time_to_full;
-       s16 battery_status;
+       s16 battery_state;
 };
 
 struct acpi_battery_alarm {
@@ -146,9 +165,9 @@ struct acpi_battery_alarm {
 
 struct acpi_battery {
        int alive;
-       int battery_present;
        int id;
        int init_state;
+       int battery_present;
        struct acpi_sbs *sbs;
        struct acpi_battery_info info;
        struct acpi_battery_state state;
@@ -158,186 +177,251 @@ struct acpi_battery {
 
 struct acpi_sbs {
        acpi_handle handle;
+       int base;
        struct acpi_device *device;
        struct acpi_ec_smbus *smbus;
+       struct mutex mutex;
        int sbsm_present;
        int sbsm_batteries_supported;
-       int ac_present;
        struct proc_dir_entry *ac_entry;
+       struct acpi_ac ac;
        struct acpi_battery battery[MAX_SBS_BAT];
-       int update_info_mode;
        int zombie;
-       int update_time;
-       int update_time2;
        struct timer_list update_timer;
+       int run_cnt;
+       int update_proc_flg;
 };
 
-static void acpi_update_delay(struct acpi_sbs *sbs);
-static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type);
+static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type);
+static void acpi_sbs_update_time(void *data);
+
+union sbs_rw_data {
+       u16 word;
+       u8 block[ACPI_SBS_BLOCK_MAX + 2];
+};
+
+static int acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr,
+                             char read_write, u8 command, int size,
+                             union sbs_rw_data *data);
 
 /* --------------------------------------------------------------------------
                                SMBus Communication
    -------------------------------------------------------------------------- */
 
-static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus)
+static int acpi_ec_sbs_read(struct acpi_sbs *sbs, u8 address, u8 * data)
 {
-       union i2c_smbus_data data;
-       int result = 0;
-       char *err_str;
-       int err_number;
+       u8 val;
+       int err;
 
-       data.word = 0;
+       err = ec_read(sbs->base + address, &val);
+       if (!err) {
+               *data = val;
+       }
+       xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP);
+       return (err);
+}
 
-       result = smbus->adapter.algo->
-           smbus_xfer(&smbus->adapter,
-                      ACPI_SB_SMBUS_ADDR,
-                      0, I2C_SMBUS_READ, 0x16, I2C_SMBUS_BLOCK_DATA, &data);
+static int acpi_ec_sbs_write(struct acpi_sbs *sbs, u8 address, u8 data)
+{
+       int err;
 
-       err_number = (data.word & 0x000f);
+       err = ec_write(sbs->base + address, data);
+       return (err);
+}
 
-       switch (data.word & 0x000f) {
-       case 0x0000:
-               err_str = "unexpected bus error";
-               break;
-       case 0x0001:
-               err_str = "busy";
-               break;
-       case 0x0002:
-               err_str = "reserved command";
-               break;
-       case 0x0003:
-               err_str = "unsupported command";
-               break;
-       case 0x0004:
-               err_str = "access denied";
+static int
+acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr,
+                  char read_write, u8 command, int size,
+                  union sbs_rw_data *data)
+{
+       unsigned char protocol, len = 0, temp[2] = { 0, 0 };
+       int i;
+
+       if (read_write == ACPI_SBS_SMBUS_READ) {
+               protocol = ACPI_EC_SMB_PRTCL_READ;
+       } else {
+               protocol = ACPI_EC_SMB_PRTCL_WRITE;
+       }
+
+       switch (size) {
+
+       case ACPI_SBS_WORD_DATA:
+               acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command);
+               if (read_write == ACPI_SBS_SMBUS_WRITE) {
+                       acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA, data->word);
+                       acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + 1,
+                                         data->word >> 8);
+               }
+               protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA;
                break;
-       case 0x0005:
-               err_str = "overflow/underflow";
+       case ACPI_SBS_BLOCK_DATA:
+               acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command);
+               if (read_write == ACPI_SBS_SMBUS_WRITE) {
+                       len = min_t(u8, data->block[0], 32);
+                       acpi_ec_sbs_write(sbs, ACPI_EC_SMB_BCNT, len);
+                       for (i = 0; i < len; i++)
+                               acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + i,
+                                                 data->block[i + 1]);
+               }
+               protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA;
                break;
-       case 0x0006:
-               err_str = "bad size";
+       default:
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "unsupported transaction %d", size));
+               return (-1);
+       }
+
+       acpi_ec_sbs_write(sbs, ACPI_EC_SMB_ADDR, addr << 1);
+       acpi_ec_sbs_write(sbs, ACPI_EC_SMB_PRTCL, protocol);
+
+       acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
+
+       if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
+               xmsleep(ACPI_EC_SMB_ACCESS_SLEEP1);
+               acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
+       }
+       if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
+               xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2);
+               acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
+       }
+       if ((~temp[0] & ACPI_EC_SMB_STS_DONE)
+           || (temp[0] & ACPI_EC_SMB_STS_STATUS)) {
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "transaction %d error", size));
+               return (-1);
+       }
+
+       if (read_write == ACPI_SBS_SMBUS_WRITE) {
+               return (0);
+       }
+
+       switch (size) {
+
+       case ACPI_SBS_WORD_DATA:
+               acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA, temp);
+               acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + 1, temp + 1);
+               data->word = (temp[1] << 8) | temp[0];
                break;
-       case 0x0007:
-               err_str = "unknown error";
+
+       case ACPI_SBS_BLOCK_DATA:
+               len = 0;
+               acpi_ec_sbs_read(sbs, ACPI_EC_SMB_BCNT, &len);
+               len = min_t(u8, len, 32);
+               for (i = 0; i < len; i++)
+                       acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + i,
+                                        data->block + i + 1);
+               data->block[0] = len;
                break;
        default:
-               err_str = "unrecognized error";
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "unsupported transaction %d", size));
+               return (-1);
        }
-       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                         "%s: ret %i, err %i\n", err_str, result, err_number));
+
+       return (0);
 }
 
 static int
-acpi_sbs_smbus_read_word(struct acpi_ec_smbus *smbus, int addr, int func,
-                        u16 * word,
-                        void (*err_handler) (struct acpi_ec_smbus * smbus))
+acpi_sbs_read_word(struct acpi_sbs *sbs, int addr, int func, u16 * word)
 {
-       union i2c_smbus_data data;
+       union sbs_rw_data data;
        int result = 0;
-       int i;
 
-       if (err_handler == NULL) {
-               err_handler = acpi_battery_smbus_err_handler;
-       }
-
-       for (i = 0; i < MAX_SMBUS_ERR; i++) {
-               result =
-                   smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
-                                                   I2C_SMBUS_READ, func,
-                                                   I2C_SMBUS_WORD_DATA, &data);
-               if (result) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "try %i: smbus->adapter.algo->smbus_xfer() failed\n",
-                                         i));
-                       if (err_handler) {
-                               err_handler(smbus);
-                       }
-               } else {
-                       *word = data.word;
-                       break;
-               }
+       result = acpi_ec_sbs_access(sbs, addr,
+                                   ACPI_SBS_SMBUS_READ, func,
+                                   ACPI_SBS_WORD_DATA, &data);
+       if (result) {
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_ec_sbs_access() failed"));
+       } else {
+               *word = data.word;
        }
 
        return result;
 }
 
 static int
-acpi_sbs_smbus_read_str(struct acpi_ec_smbus *smbus, int addr, int func,
-                       char *str,
-                       void (*err_handler) (struct acpi_ec_smbus * smbus))
+acpi_sbs_read_str(struct acpi_sbs *sbs, int addr, int func, char *str)
 {
-       union i2c_smbus_data data;
+       union sbs_rw_data data;
        int result = 0;
-       int i;
-
-       if (err_handler == NULL) {
-               err_handler = acpi_battery_smbus_err_handler;
-       }
 
-       for (i = 0; i < MAX_SMBUS_ERR; i++) {
-               result =
-                   smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
-                                                   I2C_SMBUS_READ, func,
-                                                   I2C_SMBUS_BLOCK_DATA,
-                                                   &data);
-               if (result) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "try %i: smbus->adapter.algo->smbus_xfer() failed\n",
-                                         i));
-                       if (err_handler) {
-                               err_handler(smbus);
-                       }
-               } else {
-                       strncpy(str, (const char *)data.block + 1,
-                               data.block[0]);
-                       str[data.block[0]] = 0;
-                       break;
-               }
+       result = acpi_ec_sbs_access(sbs, addr,
+                                   ACPI_SBS_SMBUS_READ, func,
+                                   ACPI_SBS_BLOCK_DATA, &data);
+       if (result) {
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_ec_sbs_access() failed"));
+       } else {
+               strncpy(str, (const char *)data.block + 1, data.block[0]);
+               str[data.block[0]] = 0;
        }
 
        return result;
 }
 
 static int
-acpi_sbs_smbus_write_word(struct acpi_ec_smbus *smbus, int addr, int func,
-                         int word,
-                         void (*err_handler) (struct acpi_ec_smbus * smbus))
+acpi_sbs_write_word(struct acpi_sbs *sbs, int addr, int func, int word)
 {
-       union i2c_smbus_data data;
+       union sbs_rw_data data;
        int result = 0;
-       int i;
-
-       if (err_handler == NULL) {
-               err_handler = acpi_battery_smbus_err_handler;
-       }
 
        data.word = word;
 
-       for (i = 0; i < MAX_SMBUS_ERR; i++) {
-               result =
-                   smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
-                                                   I2C_SMBUS_WRITE, func,
-                                                   I2C_SMBUS_WORD_DATA, &data);
-               if (result) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "try %i: smbus->adapter.algo"
-                                         "->smbus_xfer() failed\n", i));
-                       if (err_handler) {
-                               err_handler(smbus);
-                       }
-               } else {
-                       break;
-               }
+       result = acpi_ec_sbs_access(sbs, addr,
+                                   ACPI_SBS_SMBUS_WRITE, func,
+                                   ACPI_SBS_WORD_DATA, &data);
+       if (result) {
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_ec_sbs_access() failed"));
        }
 
        return result;
 }
 
+static int sbs_zombie(struct acpi_sbs *sbs)
+{
+       return (sbs->zombie);
+}
+
+static int sbs_mutex_lock(struct acpi_sbs *sbs)
+{
+       if (sbs_zombie(sbs)) {
+               return -ENODEV;
+       }
+       mutex_lock(&sbs->mutex);
+       return 0;
+}
+
+static void sbs_mutex_unlock(struct acpi_sbs *sbs)
+{
+       mutex_unlock(&sbs->mutex);
+}
+
 /* --------------------------------------------------------------------------
                             Smart Battery System Management
    -------------------------------------------------------------------------- */
 
-/* Smart Battery */
+static int acpi_check_update_proc(struct acpi_sbs *sbs)
+{
+       acpi_status status = AE_OK;
+
+       if (update_time == 0) {
+               sbs->update_proc_flg = 0;
+               return 0;
+       }
+       if (sbs->update_proc_flg == 0) {
+               status = acpi_os_execute(OSL_GPE_HANDLER,
+                                        acpi_sbs_update_time, sbs);
+               if (status != AE_OK) {
+                       ACPI_EXCEPTION((AE_INFO, status,
+                                       "acpi_os_execute() failed"));
+                       return 1;
+               }
+               sbs->update_proc_flg = 1;
+       }
+       return 0;
+}
 
 static int acpi_sbs_generate_event(struct acpi_device *device,
                                   int event, int state, char *bid, char *class)
@@ -366,12 +450,11 @@ static int acpi_battery_get_present(struct acpi_battery *battery)
        int result = 0;
        int is_present = 0;
 
-       result = acpi_sbs_smbus_read_word(battery->sbs->smbus,
-                                         ACPI_SBSM_SMBUS_ADDR, 0x01,
-                                         &state, NULL);
+       result = acpi_sbs_read_word(battery->sbs,
+                                   ACPI_SBSM_SMBUS_ADDR, 0x01, &state);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
        }
        if (!result) {
                is_present = (state & 0x000f) & (1 << battery->id);
@@ -381,45 +464,33 @@ static int acpi_battery_get_present(struct acpi_battery *battery)
        return result;
 }
 
-static int acpi_battery_is_present(struct acpi_battery *battery)
-{
-       return (battery->battery_present);
-}
-
-static int acpi_ac_is_present(struct acpi_sbs *sbs)
-{
-       return (sbs->ac_present);
-}
-
 static int acpi_battery_select(struct acpi_battery *battery)
 {
-       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       struct acpi_sbs *sbs = battery->sbs;
        int result = 0;
        s16 state;
        int foo;
 
-       if (battery->sbs->sbsm_present) {
+       if (sbs->sbsm_present) {
 
                /* Take special care not to knobble other nibbles of
                 * state (aka selector_state), since
                 * it causes charging to halt on SBSELs */
 
                result =
-                   acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01,
-                                            &state, NULL);
+                   acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, &state);
                if (result) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "acpi_sbs_smbus_read_word() failed\n"));
+                       ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                                       "acpi_sbs_read_word() failed"));
                        goto end;
                }
 
                foo = (state & 0x0fff) | (1 << (battery->id + 12));
                result =
-                   acpi_sbs_smbus_write_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01,
-                                             foo, NULL);
+                   acpi_sbs_write_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, foo);
                if (result) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "acpi_sbs_smbus_write_word() failed\n"));
+                       ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                                       "acpi_sbs_write_word() failed"));
                        goto end;
                }
        }
@@ -430,15 +501,14 @@ static int acpi_battery_select(struct acpi_battery *battery)
 
 static int acpi_sbsm_get_info(struct acpi_sbs *sbs)
 {
-       struct acpi_ec_smbus *smbus = sbs->smbus;
        int result = 0;
        s16 battery_system_info;
 
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x04,
-                                         &battery_system_info, NULL);
+       result = acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x04,
+                                   &battery_system_info);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
@@ -451,53 +521,50 @@ static int acpi_sbsm_get_info(struct acpi_sbs *sbs)
 
 static int acpi_battery_get_info(struct acpi_battery *battery)
 {
-       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       struct acpi_sbs *sbs = battery->sbs;
        int result = 0;
        s16 battery_mode;
        s16 specification_info;
 
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03,
-                                         &battery_mode,
-                                         &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03,
+                                   &battery_mode);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
        battery->info.capacity_mode = (battery_mode & 0x8000) >> 15;
 
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x10,
-                                         &battery->info.full_charge_capacity,
-                                         &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x10,
+                                   &battery->info.full_charge_capacity);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x18,
-                                         &battery->info.design_capacity,
-                                         &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x18,
+                                   &battery->info.design_capacity);
 
        if (result) {
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x19,
-                                         &battery->info.design_voltage,
-                                         &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x19,
+                                   &battery->info.design_voltage);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1a,
-                                         &specification_info,
-                                         &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1a,
+                                   &specification_info);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
@@ -529,37 +596,35 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
                battery->info.ipscale = 1;
        }
 
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1c,
-                                         &battery->info.serial_number,
-                                         &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1c,
+                                   &battery->info.serial_number);
        if (result) {
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
-       result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x20,
-                                        battery->info.manufacturer_name,
-                                        &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x20,
+                                  battery->info.manufacturer_name);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_str() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_str() failed"));
                goto end;
        }
 
-       result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x21,
-                                        battery->info.device_name,
-                                        &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x21,
+                                  battery->info.device_name);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_str() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_str() failed"));
                goto end;
        }
 
-       result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x22,
-                                        battery->info.device_chemistry,
-                                        &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x22,
+                                  battery->info.device_chemistry);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_str() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_str() failed"));
                goto end;
        }
 
@@ -567,103 +632,60 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
        return result;
 }
 
-static void acpi_update_delay(struct acpi_sbs *sbs)
-{
-       if (sbs->zombie) {
-               return;
-       }
-       if (sbs->update_time2 > 0) {
-               msleep(sbs->update_time2 * 1000);
-       }
-}
-
 static int acpi_battery_get_state(struct acpi_battery *battery)
 {
-       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       struct acpi_sbs *sbs = battery->sbs;
        int result = 0;
 
-       acpi_update_delay(battery->sbs);
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x09,
-                                         &battery->state.voltage,
-                                         &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x09,
+                                   &battery->state.voltage);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
-       acpi_update_delay(battery->sbs);
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0a,
-                                         &battery->state.amperage,
-                                         &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0a,
+                                   &battery->state.amperage);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
-       acpi_update_delay(battery->sbs);
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0f,
-                                         &battery->state.remaining_capacity,
-                                         &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0f,
+                                   &battery->state.remaining_capacity);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
-       acpi_update_delay(battery->sbs);
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x12,
-                                         &battery->state.average_time_to_empty,
-                                         &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x16,
+                                   &battery->state.battery_state);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
-       acpi_update_delay(battery->sbs);
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x13,
-                                         &battery->state.average_time_to_full,
-                                         &acpi_battery_smbus_err_handler);
-       if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
-               goto end;
-       }
-
-       acpi_update_delay(battery->sbs);
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x16,
-                                         &battery->state.battery_status,
-                                         &acpi_battery_smbus_err_handler);
-       if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
-               goto end;
-       }
-
-       acpi_update_delay(battery->sbs);
-
       end:
        return result;
 }
 
 static int acpi_battery_get_alarm(struct acpi_battery *battery)
 {
-       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       struct acpi_sbs *sbs = battery->sbs;
        int result = 0;
 
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
-                                         &battery->alarm.remaining_capacity,
-                                         &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01,
+                                   &battery->alarm.remaining_capacity);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
-       acpi_update_delay(battery->sbs);
-
       end:
 
        return result;
@@ -672,15 +694,15 @@ static int acpi_battery_get_alarm(struct acpi_battery *battery)
 static int acpi_battery_set_alarm(struct acpi_battery *battery,
                                  unsigned long alarm)
 {
-       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       struct acpi_sbs *sbs = battery->sbs;
        int result = 0;
        s16 battery_mode;
        int foo;
 
        result = acpi_battery_select(battery);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_battery_select() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_battery_select() failed"));
                goto end;
        }
 
@@ -688,33 +710,29 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery,
 
        if (alarm > 0) {
                result =
-                   acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03,
-                                            &battery_mode,
-                                            &acpi_battery_smbus_err_handler);
+                   acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03,
+                                      &battery_mode);
                if (result) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "acpi_sbs_smbus_read_word() failed\n"));
+                       ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                                       "acpi_sbs_read_word() failed"));
                        goto end;
                }
 
                result =
-                   acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
-                                             battery_mode & 0xbfff,
-                                             &acpi_battery_smbus_err_handler);
+                   acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01,
+                                       battery_mode & 0xbfff);
                if (result) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "acpi_sbs_smbus_write_word() failed\n"));
+                       ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                                       "acpi_sbs_write_word() failed"));
                        goto end;
                }
        }
 
        foo = alarm / (battery->info.capacity_mode ? 10 : 1);
-       result = acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
-                                          foo,
-                                          &acpi_battery_smbus_err_handler);
+       result = acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01, foo);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_write_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_write_word() failed"));
                goto end;
        }
 
@@ -725,6 +743,7 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery,
 
 static int acpi_battery_set_mode(struct acpi_battery *battery)
 {
+       struct acpi_sbs *sbs = battery->sbs;
        int result = 0;
        s16 battery_mode;
 
@@ -732,12 +751,11 @@ static int acpi_battery_set_mode(struct acpi_battery *battery)
                goto end;
        }
 
-       result = acpi_sbs_smbus_read_word(battery->sbs->smbus,
-                                         ACPI_SB_SMBUS_ADDR, 0x03,
-                                         &battery_mode, NULL);
+       result = acpi_sbs_read_word(sbs,
+                                   ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
@@ -746,21 +764,19 @@ static int acpi_battery_set_mode(struct acpi_battery *battery)
        } else {
                battery_mode |= 0x8000;
        }
-       result = acpi_sbs_smbus_write_word(battery->sbs->smbus,
-                                          ACPI_SB_SMBUS_ADDR, 0x03,
-                                          battery_mode, NULL);
+       result = acpi_sbs_write_word(sbs,
+                                    ACPI_SB_SMBUS_ADDR, 0x03, battery_mode);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_write_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_write_word() failed"));
                goto end;
        }
 
-       result = acpi_sbs_smbus_read_word(battery->sbs->smbus,
-                                         ACPI_SB_SMBUS_ADDR, 0x03,
-                                         &battery_mode, NULL);
+       result = acpi_sbs_read_word(sbs,
+                                   ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
@@ -774,36 +790,36 @@ static int acpi_battery_init(struct acpi_battery *battery)
 
        result = acpi_battery_select(battery);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_battery_init() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_battery_select() failed"));
                goto end;
        }
 
        result = acpi_battery_set_mode(battery);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_battery_set_mode() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_battery_set_mode() failed"));
                goto end;
        }
 
        result = acpi_battery_get_info(battery);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_battery_get_info() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_battery_get_info() failed"));
                goto end;
        }
 
        result = acpi_battery_get_state(battery);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_battery_get_state() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_battery_get_state() failed"));
                goto end;
        }
 
        result = acpi_battery_get_alarm(battery);
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_battery_get_alarm() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_battery_get_alarm() failed"));
                goto end;
        }
 
@@ -813,20 +829,19 @@ static int acpi_battery_init(struct acpi_battery *battery)
 
 static int acpi_ac_get_present(struct acpi_sbs *sbs)
 {
-       struct acpi_ec_smbus *smbus = sbs->smbus;
        int result = 0;
        s16 charger_status;
 
-       result = acpi_sbs_smbus_read_word(smbus, ACPI_SBC_SMBUS_ADDR, 0x13,
-                                         &charger_status, NULL);
+       result = acpi_sbs_read_word(sbs, ACPI_SBC_SMBUS_ADDR, 0x13,
+                                   &charger_status);
 
        if (result) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "acpi_sbs_smbus_read_word() failed\n"));
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                               "acpi_sbs_read_word() failed"));
                goto end;
        }
 
-       sbs->ac_present = (charger_status & 0x8000) >> 15;
+       sbs->ac.ac_present = (charger_status & 0x8000) >> 15;
 
       end:
 
@@ -852,8 +867,8 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
        if (!*dir) {
                *dir = proc_mkdir(dir_name, parent_dir);
                if (!*dir) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "proc_mkdir() failed\n"));
+                       ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                                       "proc_mkdir() failed"));
                        return -ENODEV;
                }
                (*dir)->owner = THIS_MODULE;
@@ -863,8 +878,8 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
        if (info_fops) {
                entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
                if (!entry) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "create_proc_entry() failed\n"));
+                       ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                                       "create_proc_entry() failed"));
                } else {
                        entry->proc_fops = info_fops;
                        entry->data = data;
@@ -876,8 +891,8 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
        if (state_fops) {
                entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
                if (!entry) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "create_proc_entry() failed\n"));
+                       ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                                       "create_proc_entry() failed"));
                } else {
                        entry->proc_fops = state_fops;
                        entry->data = data;
@@ -889,8 +904,8 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
        if (alarm_fops) {
                entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
                if (!entry) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "create_proc_entry() failed\n"));
+                       ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                                       "create_proc_entry() failed"));
                } else {
                        entry->proc_fops = alarm_fops;
                        entry->data = data;
@@ -923,24 +938,27 @@ static struct proc_dir_entry *acpi_battery_dir = NULL;
 static int acpi_battery_read_info(struct seq_file *seq, void *offset)
 {
        struct acpi_battery *battery = seq->private;
+       struct acpi_sbs *sbs = battery->sbs;
        int cscale;
        int result = 0;
 
-       if (battery->sbs->zombie) {
+       if (sbs_mutex_lock(sbs)) {
                return -ENODEV;
        }
 
-       down(&sbs_sem);
+       result = acpi_check_update_proc(sbs);
+       if (result)
+               goto end;
 
-       if (update_mode == REQUEST_UPDATE_MODE) {
-               result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_INFO);
+       if (update_time == 0) {
+               result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_INFO);
                if (result) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "acpi_sbs_update_run() failed\n"));
+                       ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+                                       "acpi_sbs_update_run() failed"));
                }
        }
 
-       if (acpi_battery_is_present(battery)) {
+       if (battery->battery_present) {
                seq_printf(seq, "present:                 yes\n");
        } else {
                seq_printf(seq, "present:                 no\n");
@@ -952,13 +970,13 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
        } else {
                cscale = battery->info.ipscale;
        }
-  &n