linux-old/arch/sparc64/kernel/power.c
<<
>>
Prefs
   1/* $Id: power.c,v 1.9.2.1 2001/12/11 01:57:49 davem Exp $
   2 * power.c: Power management driver.
   3 *
   4 * Copyright (C) 1999 David S. Miller (davem@redhat.com)
   5 */
   6
   7#include <linux/config.h>
   8#include <linux/kernel.h>
   9#include <linux/init.h>
  10#include <linux/sched.h>
  11#include <linux/signal.h>
  12#include <linux/delay.h>
  13
  14#include <asm/ebus.h>
  15#include <asm/auxio.h>
  16
  17#define __KERNEL_SYSCALLS__
  18#include <linux/unistd.h>
  19
  20/*
  21 * sysctl - toggle power-off restriction for serial console 
  22 * systems in machine_power_off()
  23 */
  24int scons_pwroff = 1; 
  25
  26#ifdef CONFIG_PCI
  27static unsigned long power_reg = 0UL;
  28
  29static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
  30static int button_pressed;
  31
  32static void power_handler(int irq, void *dev_id, struct pt_regs *regs)
  33{
  34        if (button_pressed == 0) {
  35                wake_up(&powerd_wait);
  36                button_pressed = 1;
  37        }
  38}
  39#endif /* CONFIG_PCI */
  40
  41extern void machine_halt(void);
  42extern void machine_alt_power_off(void);
  43static void (*poweroff_method)(void) = machine_alt_power_off;
  44
  45extern int serial_console;
  46
  47void machine_power_off(void)
  48{
  49        if (!serial_console || scons_pwroff) {
  50#ifdef CONFIG_PCI
  51                if (power_reg != 0UL) {
  52                        /* Both register bits seem to have the
  53                         * same effect, so until I figure out
  54                         * what the difference is...
  55                         */
  56                        writel(AUXIO_PCIO_CPWR_OFF | AUXIO_PCIO_SPWR_OFF, power_reg);
  57                } else
  58#endif /* CONFIG_PCI */
  59                        if (poweroff_method != NULL) {
  60                                poweroff_method();
  61                                /* not reached */
  62                        }
  63        }
  64        machine_halt();
  65}
  66
  67#ifdef CONFIG_PCI
  68static int powerd(void *__unused)
  69{
  70        static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
  71        char *argv[] = { "/sbin/shutdown", "-h", "now", NULL };
  72
  73        daemonize();
  74        sprintf(current->comm, "powerd");
  75
  76again:
  77        while (button_pressed == 0) {
  78                spin_lock_irq(&current->sigmask_lock);
  79                flush_signals(current);
  80                spin_unlock_irq(&current->sigmask_lock);
  81                interruptible_sleep_on(&powerd_wait);
  82        }
  83
  84        /* Ok, down we go... */
  85        if (execve("/sbin/shutdown", argv, envp) < 0) {
  86                printk("powerd: shutdown execution failed\n");
  87                button_pressed = 0;
  88                goto again;
  89        }
  90        return 0;
  91}
  92
  93static int __init has_button_interrupt(struct linux_ebus_device *edev)
  94{
  95        if (edev->irqs[0] == PCI_IRQ_NONE)
  96                return 0;
  97        if (!prom_node_has_property(edev->prom_node, "button"))
  98                return 0;
  99
 100        return 1;
 101}
 102
 103void __init power_init(void)
 104{
 105        struct linux_ebus *ebus;
 106        struct linux_ebus_device *edev;
 107        static int invoked;
 108
 109        if (invoked)
 110                return;
 111        invoked = 1;
 112
 113        for_each_ebus(ebus) {
 114                for_each_ebusdev(edev, ebus) {
 115                        if (!strcmp(edev->prom_name, "power"))
 116                                goto found;
 117                }
 118        }
 119        return;
 120
 121found:
 122        power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4);
 123        printk("power: Control reg at %016lx ... ", power_reg);
 124        poweroff_method = machine_halt; /* able to use the standard poweroff */
 125        if (has_button_interrupt(edev)) {
 126                if (kernel_thread(powerd, 0, CLONE_FS) < 0) {
 127                        printk("Failed to start power daemon.\n");
 128                        return;
 129                }
 130                printk("powerd running.\n");
 131
 132                if (request_irq(edev->irqs[0],
 133                                power_handler, SA_SHIRQ, "power",
 134                                (void *) power_reg) < 0)
 135                        printk("power: Error, cannot register IRQ handler.\n");
 136        } else {
 137                printk("not using powerd.\n");
 138        }
 139}
 140#endif /* CONFIG_PCI */
 141
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.