linux/arch/x86/platform/iris/iris.c
<<
>>
Prefs
   1/*
   2 * Eurobraille/Iris power off support.
   3 *
   4 * Eurobraille's Iris machine is a PC with no APM or ACPI support.
   5 * It is shutdown by a special I/O sequence which this module provides.
   6 *
   7 *  Copyright (C) Shérab <Sebastien.Hinderer@ens-lyon.org>
   8 *
   9 * This program is free software ; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation ; either version 2 of the License, or
  12 * (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY ; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with the program ; if not, write to the Free Software
  21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22 */
  23
  24#include <linux/moduleparam.h>
  25#include <linux/module.h>
  26#include <linux/platform_device.h>
  27#include <linux/kernel.h>
  28#include <linux/errno.h>
  29#include <linux/delay.h>
  30#include <linux/pm.h>
  31#include <asm/io.h>
  32
  33#define IRIS_GIO_BASE           0x340
  34#define IRIS_GIO_INPUT          IRIS_GIO_BASE
  35#define IRIS_GIO_OUTPUT         (IRIS_GIO_BASE + 1)
  36#define IRIS_GIO_PULSE          0x80 /* First byte to send */
  37#define IRIS_GIO_REST           0x00 /* Second byte to send */
  38#define IRIS_GIO_NODEV          0xff /* Likely not an Iris */
  39
  40MODULE_LICENSE("GPL");
  41MODULE_AUTHOR("Sébastien Hinderer <Sebastien.Hinderer@ens-lyon.org>");
  42MODULE_DESCRIPTION("A power_off handler for Iris devices from EuroBraille");
  43MODULE_SUPPORTED_DEVICE("Eurobraille/Iris");
  44
  45static bool force;
  46
  47module_param(force, bool, 0);
  48MODULE_PARM_DESC(force, "Set to one to force poweroff handler installation.");
  49
  50static void (*old_pm_power_off)(void);
  51
  52static void iris_power_off(void)
  53{
  54        outb(IRIS_GIO_PULSE, IRIS_GIO_OUTPUT);
  55        msleep(850);
  56        outb(IRIS_GIO_REST, IRIS_GIO_OUTPUT);
  57}
  58
  59/*
  60 * Before installing the power_off handler, try to make sure the OS is
  61 * running on an Iris.  Since Iris does not support DMI, this is done
  62 * by reading its input port and seeing whether the read value is
  63 * meaningful.
  64 */
  65static int iris_probe(struct platform_device *pdev)
  66{
  67        unsigned char status = inb(IRIS_GIO_INPUT);
  68        if (status == IRIS_GIO_NODEV) {
  69                printk(KERN_ERR "This machine does not seem to be an Iris. "
  70                        "Power off handler not installed.\n");
  71                return -ENODEV;
  72        }
  73        old_pm_power_off = pm_power_off;
  74        pm_power_off = &iris_power_off;
  75        printk(KERN_INFO "Iris power_off handler installed.\n");
  76        return 0;
  77}
  78
  79static int iris_remove(struct platform_device *pdev)
  80{
  81        pm_power_off = old_pm_power_off;
  82        printk(KERN_INFO "Iris power_off handler uninstalled.\n");
  83        return 0;
  84}
  85
  86static struct platform_driver iris_driver = {
  87        .driver         = {
  88                .name   = "iris",
  89        },
  90        .probe          = iris_probe,
  91        .remove         = iris_remove,
  92};
  93
  94static struct resource iris_resources[] = {
  95        {
  96                .start  = IRIS_GIO_BASE,
  97                .end    = IRIS_GIO_OUTPUT,
  98                .flags  = IORESOURCE_IO,
  99                .name   = "address"
 100        }
 101};
 102
 103static struct platform_device *iris_device;
 104
 105static int iris_init(void)
 106{
 107        int ret;
 108        if (force != 1) {
 109                printk(KERN_ERR "The force parameter has not been set to 1."
 110                        " The Iris poweroff handler will not be installed.\n");
 111                return -ENODEV;
 112        }
 113        ret = platform_driver_register(&iris_driver);
 114        if (ret < 0) {
 115                printk(KERN_ERR "Failed to register iris platform driver: %d\n",
 116                        ret);
 117                return ret;
 118        }
 119        iris_device = platform_device_register_simple("iris", (-1),
 120                                iris_resources, ARRAY_SIZE(iris_resources));
 121        if (IS_ERR(iris_device)) {
 122                printk(KERN_ERR "Failed to register iris platform device\n");
 123                platform_driver_unregister(&iris_driver);
 124                return PTR_ERR(iris_device);
 125        }
 126        return 0;
 127}
 128
 129static void iris_exit(void)
 130{
 131        platform_device_unregister(iris_device);
 132        platform_driver_unregister(&iris_driver);
 133}
 134
 135module_init(iris_init);
 136module_exit(iris_exit);
 137